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

8 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();
  }

}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Wol*_*ang 15

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

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

  • @Stephen我认为问题的主要内容是关于任务的原子性.这就是我引用这部分规范的原因.如果我理解正确,那么即使不使用volatile也能保证这种原子性.然而,它可能发生,其他线程永远不会看到变量的更新并继续看到"旧"引用.但是,线程永远不会看到"对某个其他对象的引用或损坏的引用值". (5认同)
  • @unknown:引用的文字没有说出你的想法!实际上,JLS中的下一个子弹说:"在没有显式同步的情况下,实现可以按照可能令人惊讶的顺序更新主内存.因此,喜欢避免意外的程序员应该使用显式同步. " (3认同)
  • @unknown:OP代码安全的唯一原因是他已将变量声明为“ volatile”。 (2认同)
  • @ user1944408-您的意思是....?是的,在某些情况下,您无需使用“ volatile”或显式同步就可以证明代码可以正常工作。在这种情况下,之所以起作用是因为“哈希”有两种可能的状态(JLS如此说),并且代码在两种状态下均给出了正确的答案。 (2认同)