简体   繁体   English

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

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

Given the following code: 给出以下代码:

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

}

The Thread-Class will update the myConfigData Membervariable regularly (via an Executor every 5 minutes). Thread-Class将定期更新myConfigData Member变量(每5分钟通过一个Executor)。 Is the setting of of myConfigData in the "external" Thread threadsafe (atomic), or do I have to synchronize every Read and Write operation to the myConfigData Variable? myConfigData的设置是在“外部”线程threadafe(原子)中,还是我必须将每个Read和Write操作同步到myConfigData变量?

EDIT: The question is not whether ConcurrentHashMap is threadsafe (it is according to javadoc) but rather the setting of the ConcurrentHashMap itself in the myConfigData Member variable. 编辑:问题不是ConcurrentHashMap是线程安全的(它是根据javadoc)而是在myConfigData Member变量中设置ConcurrentHashMap本身。 This variable might be read and written "at once" by several threads so the question is whether the setting is atomic or not. 这个变量可能被几个线程“一次”读取和写入,所以问题是该设置是否是原子的。 I think this can be generalized to "Is the setting of a Java reference variable atomic or not?". 我认为这可以概括为“Java引用变量的设置是否为原子?”。

(I also made it volatile. This is a different issue and has nothing to do with atomicity - my question - but rather "visibility in other threads" and the happens-before relationship.) (我也使它变得不稳定。这是一个不同的问题,与原子性无关 - 我的问题 - 而是“其他线程中的可见性”和之前发生的关系。)

Replacing references is safe. 更换参考文献是安全的。 See Java language Specification : 请参阅Java语言规范

When a thread uses the value of a variable, the value it obtains is in fact a value stored into the variable by that thread or by some other thread. 当线程使用变量的值时,它获得的值实际上是由该线程或某个其他线程存储到变量中的值。 This is true even if the program does not contain code for proper synchronization. 即使程序不包含正确同步的代码,也是如此。 For example, if two threads store references to different objects into the same reference value, the variable will subsequently contain a reference to one object or the other, not a reference to some other object or a corrupted reference value. 例如,如果两个线程将对不同对象的引用存储到同一引用值中,则该变量随后将包含对一个对象或另一个对象的引用,而不是对某个其他对象的引用或损坏的引用值。 (There is a special exception for long and double values; see §17.4.) (长值和双值有一个特殊例外;见§17.4。)

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

ConcurrentHashMp is: ConcurrentHashMp是:

A hash table supporting full concurrency of retrievals and adjustable expected concurrency for updates. 一个哈希表,支持检索的完全并发性和可更新的预期并发性。 This class obeys the same functional specification as Hashtable, and includes versions of methods corresponding to each method of Hashtable. 该类遵循与Hashtable相同的功能规范,并包括与Hashtable的每个方法相对应的方法版本。 However, even though all operations are thread-safe, retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access. 但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。 This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details. 在依赖于线程安全但不依赖于其同步细节的程序中,此类可与Hashtable完全互操作。

The javadocs say that it's thread safe. javadocs说它是线程安全的。

Seems like a lot of work and CPU cycles to set configuration. 似乎需要很多工作和CPU周期来设置配置。 Is it truly this dynamic? 真的是这种动态吗? Or do you change once a month and just need a service bounce when you do? 或者你每个月换一次,当你这样做时只需要服务反弹?

If by update you mean overwrite an entry inside the ConcurrentHashMap: 如果通过更新,则表示覆盖ConcurrentHashMap中的条目:

FooBar.myConfigData.put(somekey, somevalue);

Then it is definitely thread safe, as duffymo said. 然后它确实是线程安全的,正如duffymo所说。

If you want to overwrite the myConfigData variable with a new value: 如果要使用新值覆盖myConfigData变量:

FooBar.myConfigData = new ConcurrentHashMap();

It is also thread-safe, as you have correctly labelled the variable as volatile. 它也是线程安全的,因为您已正确将变量标记为volatile。 The volatile keyword means that multiple threads can access the same variable safely and atomically. volatile关键字意味着多个线程可以安全地和原子地访问同一个变量。

EDIT: The Question is not wether ConcurrentHashMap is threadsafe (it is according to javadoc) but rather the Setting of the ConcurrentHashMap itself in the myConfigData Member variable. 编辑:问题不在于ConcurrentHashMap是线程安全的(它是根据javadoc)而是在myConfigData Member变量中设置ConcurrentHashMap本身。 This variable might be read and written "at once" by several threads so the question is, if the setting is atomic or not. 这个变量可能被几个线程“一次”读取和写入,所以问题是,如果设置是原子的或不是。 I think this can be generalized, is the Setting of a Java Reference variable atomic or not. 我认为这可以推广,是Java参数变量的原子设置与否。

(I also made it volatile. This is a different issue and has nothing to do with atomicity (my question) but rather "visibility in other threads" and the happens before relationship). (我也使它变得不稳定。这是一个不同的问题,与原子性(我的问题)无关,而是“在其他线程中的可见性”和在关系之前发生的事情)。

Actually 'volatile' is for atomicity, nothing affects visibility, a public variable will always be visible to any thread. 实际上,'volatile' 针对原子性的,没有什么会影响可见性,任何线程都可以看到公共变量。

You could alway use AtomicReference if you feel unsure. 如果你不确定,你总是可以使用AtomicReference

Although I think in your case volatile schould be enough. 虽然我认为在你的情况下挥发性应该足够了。

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

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