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

时间:2009-08-29 11:37:01

标签: 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 Membervariable(每5分钟通过一个Executor)。 myConfigData的设置是在“外部”线程threadafe(原子)中,还是我必须将每个Read和Write操作同步到myConfigData变量?

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

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

5 个答案:

答案 0 :(得分:14)

更换参考资料是安全的。见Java language Specification

  

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

答案 1 :(得分:2)

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

答案 2 :(得分:0)

ConcurrentHashMp是:

  

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

javadocs说它是线程安全的。

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

答案 3 :(得分:0)

如果通过更新意味着覆盖ConcurrentHashMap中的条目:

FooBar.myConfigData.put(somekey, somevalue);

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

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

FooBar.myConfigData = new ConcurrentHashMap();

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

  

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

     

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

实际上'volatile'对于原子性来说是,没有什么会影响可见性,任何线程都可以看到公共变量。

答案 4 :(得分:0)

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

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