线程安全设置变量(Java)?

给出以下代码:

public class FooBar { public static volatile ConcurrentHashMap myConfigData = new ConcurrentHashMap(); } public class UpdaterThread implements Runnable { run { //Query the Data from the DB and Update the FooBar config Data FooBar.myConfigData = ConfigDataDAO.getLatestConfigFromDB(); } } 

Thread-Class将定期更新myConfigData Member变量(每5分钟通过一个Executor)。 myConfigData的设置是在“外部”线程threadafe(primefaces)中,还是我必须将每个Read和Write操作同步到myConfigData变量?

编辑:问题不是ConcurrentHashMap是线程安全的(它是根据javadoc)而是在myConfigData Member变量中设置ConcurrentHashMap本身。 这个变量可能被几个线程“一次”读取和写入,所以问题是设置是否是primefaces的。 我认为这可以推广为“Java引用变量的设置是否为primefaces?”。

(我也使它变得不稳定。这是一个不同的问题,与primefaces性无关 – 我的问题 – 而是“其他线程中的可见性”和之前发生的关系。)

更换参考文献是安全的。 请参阅Java语言规范 :

当线程使用变量的值时,它获得的值实际上是由该线程或某个其他线程存储到变量中的值。 即使程序不包含正确同步的代码,也是如此。 例如,如果两个线程将对不同对象的引用存储到同一引用值中,则该变量随后将包含对一个对象或另一个对象的引用,而不是对某个其他对象的引用或损坏的引用值。 (长值和双值有一个特殊例外;见§17.4。)

volatile保证primefaces性,可见性并充当“内存障碍”(google for it,如果你想知道这意味着什么) – 至少从Java 5开始。因此它完全符合你的要求。

ConcurrentHashMp是:

一个哈希表,支持检索的完全并发和可更新的预期并发性。 该类遵循与Hashtable相同的function规范,并包括与Hashtable的每个方法相对应的方法版本。 但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。 在依赖于线程安全但不依赖于其同步细节的程序中,此类可与Hashtable完全互操作。

javadocs说它是线程安全的。

似乎需要很多工作和CPU周期来设置配置。 真的是这种动态吗? 或者你每个月换一次,当你这样做时只需要服务反弹?

如果通过更新,则表示覆盖ConcurrentHashMap中的条目:

 FooBar.myConfigData.put(somekey, somevalue); 

然后它确实是线程安全的,正如duffymo所说。

如果要使用新值覆盖myConfigData变量:

 FooBar.myConfigData = new ConcurrentHashMap(); 

它也是线程安全的,因为您已将变量正确标记为volatile。 volatile关键字意味着多个线程可以安全地和primefaces地访问同一个变量。

编辑:问题不在于ConcurrentHashMap是线程安全的(它是根据javadoc)而是在myConfigData Member变量中设置ConcurrentHashMap本身。 这个变量可能被几个线程“一次”读取和写入,所以问题是,如果设置是primefaces的或不是。 我认为这可以概括,是否设置Java Reference变量primefaces。

(我也使它变得不稳定。这是一个不同的问题,与primefaces性(我的问题)无关,而是“在其他线程中的可见性”和在关系之前发生的事情)。

实际上’volatile’ 针对primefaces性的,没有什么会影响可见性,任何线程都可以看到公共变量。

如果你不确定,你总是可以使用AtomicReference 。

虽然我认为在你的情况下挥发性应该足够了。