Является ли обновление ссылки на немодифицируемый файл потокобезопасным

У меня есть карта (назовем ее исходной картой), которая изначально нулевая. Во время развертывания службы и каждый час после этого мне нужно обновить эту карту или, по сути, переоценить ее.

Вот как я это делаю. При обновлении я создаю новую карту и возвращаю немодифицируемое представление карты этой новой карты на мою исходную карту, теперь, когда происходит это переназначение, то есть ссылка на исходную карту изменяется, повлияет ли это на любой другой поток, в настоящее время обращающийся к оригинальная карта? Следует отметить, что во время развертывания службы исходной карте присваивается значение аналогичным образом, в основном используется та же стратегия обновления.

        private static Map<String, PricingPriceList> plInfoByName;
        TransactionData.plInfoByName = plInfo.get(0);

Здесь plInfoByName — моя исходная карта, а plInfo содержит список неизменяемых карт. Вот как заполняется список plInfo

    Map<String, PricingPriceList> plInfoByName = new HashMap<String, PricingPriceList>();
    Map<String, PricingPriceList> plInfoById = new HashMap<String, PricingPriceList>();

    try {
        stmt = dbConn.createStatement();
        stmt.setFetchSize(10000);

        rs = stmt.executeQuery(query);
        PricingPriceList plDetails = null;
        while (rs.next()) {
            plDetails = new PricingPriceList();

            //populate plDetails attributes

            plInfoByName.put(rs.getString(0), plDetails);
            plInfoById.put(rs.getString(1), plDetails);
        }

    } catch (Exception e) {
        LOGGER.ERROR("Error executing refreshPlInfo. Affected in-memory objects: plInfoByName, plInfoById.", e);
    } finally {
        try {
            if (stmt != null && !stmt.isClosed()) {
                stmt.close();
            }
            if (rs != null && !rs.isClosed()) {
                rs.close();
            }
        } catch (SQLException e) {
            LOGGER.ERROR("refreshPlInfo failed to close SQL statement or resultset.", e);
        }

    }

    // Return unmodifiable version
    List<Map<String, PricingPriceList>> plInfo = new ArrayList<Map<String, PricingPriceList>>();
    plInfo.add(Collections.unmodifiableMap(plInfoByName));
    plInfo.add(Collections.unmodifiableMap(plInfoById));
    return plInfo;

Итак, когда я это сделаю, повлияет ли это на любой поток, читающий TransactionData.plInfoByName? Или это потокобезопасно, потому что в нем хранится немодифицируемая карта.

    TransactionData.plInfoByName = plInfo.get(0);

person Arnav Sengupta    schedule 11.03.2016    source источник


Ответы (1)


unmodifiableMap сам по себе не является потокобезопасным, он просто не позволяет пользователям изменять его. Другой поток, имеющий доступ к базовой карте, может изменить ее, пока текущий поток читает.

Однако, если вы просто измените ссылку на карту, это не должно повлиять ни на один поток, который в настоящее время обращается к «старой» карте. Предполагая (мне нужно это проверить), что получение ссылки на объект является более или менее атомарной операцией (см. здесь: Какие операции в Java считаются атомарными?), любой поток, получивший ссылку на "старую" карту, должен сохранить ее до тех пор, пока он снова не получит ссылку.

Пример:

Предположим, что выполняются следующие операции:

  • переменная "map" содержит ссылку на карту A
  • T1 извлекает карту A через «карту» и сохраняет эту ссылку в некоторой локальной переменной, назовем ее «t1Map».
  • T2 теперь меняет «карту» на справочную карту B.
  • T1 обращается к карте через «t1Map», который по-прежнему ссылается на A.
  • T1 снова извлекает карту A через «map» и теперь получает ссылку на B.
person Thomas    schedule 11.03.2016
comment
Итак, нам нужно просто подтвердить, является ли эта операция присваивания в java атомарной или нет? На самом деле это то, что меня больше всего беспокоит, повлияет ли переназначение на какой-либо текущий поток. - person Arnav Sengupta; 11.03.2016
comment
@ArnavSengupta взгляните на ветку, на которую я ссылаюсь. В нем говорится, что назначения являются атомарными - мне нужно найти соответствующий раздел в JLS. - person Thomas; 11.03.2016
comment
Просто добавим, что потоки не сохраняют его в локальной переменной, все они считываются из этой общей карты TransactionData.plInfoByName. - person Arnav Sengupta; 11.03.2016
comment
Спасибо, это помогает, только что проверил, что назначения ссылок кажутся атомарными, так что все должно быть в порядке. - person Arnav Sengupta; 11.03.2016