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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1351223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 16:13:04  来源:igfitidea点击:

Thread-safe setting of a variable (Java)?

java

提问by Wolfgang

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). 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 成员变量(通过每 5 分钟执行一次)。是在“外部”线程线程安全(原子)中设置 myConfigData,还是必须将每个读取和写入操作同步到 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. 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?".

编辑:问题不在于 ConcurrentHashMap 是否是线程安全的(根据 javadoc),而是在 myConfigData Member 变量中 ConcurrentHashMap 本身的设置。这个变量可能会被多个线程“一次”读取和写入,所以问题是设置是否是原子的。我认为这可以概括为“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.)

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

回答by Wolfgang

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.)

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

回答by Kutzi

volatileguarantees atomicity, visibility and acts as a 'memory barrier' (google for it, if you want to know what that means) - at least since Java 5. Therefore it does exactly what you want.

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

回答by duffymo

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. 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相同的功能规范,包括与Hashtable的每个方法对应的方法版本。但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以防止所有访问的方式锁定整个表。在依赖其线程安全但不依赖于其同步细节的程序中,此类与 Hashtable 完全可互操作。

The javadocs say that it's thread safe.

javadocs 说它是线程安全的。

Seems like a lot of work and CPU cycles to set configuration. Is it truly this dynamic? Or do you change once a month and just need a service bounce when you do?

似乎需要大量的工作和 CPU 周期来设置配置。真的是这个动态吗?或者您是否每月更改一次,并且在更改时只需要服务退回?

回答by Will

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. The volatilekeyword 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. 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.

(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).

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

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

Actually 'volatile' isfor atomicity, nothing affects visibility, a public variable will always be visible to any thread.

实际上 'volatile'为了原子性,没有任何影响可见性,公共变量将始终对任何线程可见。

回答by zockman

You could alway use AtomicReferenceif you feel unsure.

如果您不确定,您可以随时使用AtomicReference

Although I think in your case volatile schould be enough.

虽然我认为在你的情况下 volatile 应该就足够了。