Потокобезопасная установка переменной (Java) - PullRequest
6 голосов
/ 29 августа 2009

С учетом следующего кода:

public class FooBar { 

  public static volatile ConcurrentHashMap myConfigData  = new ConcurrentHashMap();      

}

public class UpdaterThread implements Runnable { 

  public void run() {
    //Query the Data from the DB and Update the FooBar config Data
    FooBar.myConfigData = ConfigDataDAO.getLatestConfigFromDB();
  }

}

Thread-Class будет регулярно обновлять переменную myConfigData Member Member (через Исполнителя каждые 5 минут). Является ли настройка myConfigData во «внешнем» потоке потокобезопасной (атомарной) или мне нужно синхронизировать каждую операцию чтения и записи с переменной myConfigData?

РЕДАКТИРОВАТЬ: Вопрос не в том, является ли ConcurrentHashMap поточно-ориентированным (согласно javadoc), а в настройке самого ConcurrentHashMap в переменной myConfigData Member. Эта переменная может быть прочитана и записана "сразу" несколькими потоками, поэтому вопрос заключается в том, является ли параметр атомарным или нет. Я думаю, что это можно обобщить так: «Является ли установка ссылочной переменной Java атомарной или нет?».

(Я также сделал его нестабильным. Это другая проблема, и она не имеет ничего общего с атомарностью - мой вопрос, а скорее с «видимостью в других потоках» и отношениями до и после).

Ответы [ 5 ]

14 голосов
/ 29 августа 2009

Замена ссылок безопасна. См. Спецификация языка Java :

Когда поток использует значение переменной, полученное им значение фактически является значением, сохраненным в переменной этим потоком или каким-либо другим потоком. Это верно, даже если программа не содержит код для правильной синхронизации. Например, если два потока хранят ссылки на разные объекты в одном и том же ссылочном значении, переменная впоследствии будет содержать ссылку на один или другой объект, а не ссылку на какой-либо другой объект или поврежденное ссылочное значение. (Существует специальное исключение для длинных и двойных значений; см. §17.4.)

2 голосов
/ 29 августа 2009

volatile гарантирует атомарность, видимость и действует как «барьер памяти» (Google для этого, если вы хотите знать, что это значит) - по крайней мере, начиная с Java 5. Поэтому он делает именно то, что вы хотите.

0 голосов
/ 31 августа 2009

Вы всегда можете использовать AtomicReference , если чувствуете себя неуверенно.

Хотя я думаю, что в вашем случае достаточно летучих веществ.

0 голосов
/ 29 августа 2009

Если под обновлением вы подразумеваете перезаписать запись внутри ConcurrentHashMap:

FooBar.myConfigData.put(somekey, somevalue);

Тогда это определенно потокобезопасно, как сказал Даффимо.

Если вы хотите перезаписать переменную myConfigData новым значением:

FooBar.myConfigData = new ConcurrentHashMap();

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

РЕДАКТИРОВАТЬ: Вопрос не в том, является ли ConcurrentHashMap поточно-ориентированным (согласно javadoc), а в том, что касается самого параметра ConcurrentHashMap в переменной myConfigData Member. Эта переменная может быть прочитана и записана "сразу" несколькими потоками, поэтому возникает вопрос, является ли параметр атомарным или нет. Я думаю, что это может быть обобщено, является ли установка переменной Java Reference атомарной или нет.

(Я также сделал его нестабильным. Это другая проблема, и она не имеет ничего общего с атомарностью (мой вопрос), а скорее «видимость в других потоках» и то, что происходит до отношений).

На самом деле 'volatile' для атомарности , ничего не влияет на видимость, открытая переменная всегда будет видна любому потоку.

0 голосов
/ 29 августа 2009

ConcurrentHashMp - это:

Хеш-таблица, поддерживающая полный параллелизм получения и настраиваемый ожидаемый параллелизм для обновлений. Этот класс подчиняется той же функциональной спецификации, что и Hashtable, и включает версии методов, соответствующие каждому методу Hashtable. Однако, хотя все операции являются поточно-ориентированными, операции извлечения не влекут за собой блокировку, и нет никакой поддержки для блокировки всей таблицы таким образом, чтобы предотвратить любой доступ. Этот класс полностью совместим с Hashtable в программах, которые полагаются на безопасность потоков, но не на детали синхронизации.

Javadocs говорят, что это потокобезопасно.

Похоже, много работы и циклов ЦП для настройки конфигурации. Это действительно такая динамика? Или вы меняете один раз в месяц и просто нуждаетесь в отказе от обслуживания, когда вы это делаете?

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