繁体   English   中英

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

[英]Thread-safe setting of a variable (Java)?

给出以下代码:

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

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

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

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

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

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

ConcurrentHashMp是:

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

javadocs说它是线程安全的。

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

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

FooBar.myConfigData.put(somekey, somevalue);

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

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

FooBar.myConfigData = new ConcurrentHashMap();

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM