Java 在两个线程之间共享一个变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3493752/
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
Java share a variable between two threads
提问by Dave
I have two threads. One invokes the update method of a class that modifies a variable. Another invokes the update method of a class that reads the variable. Only one thread writes and one (or more) threads read that variable. What do I need to do in terms of concurrency, since I am new to multi-threading?
我有两个线程。一种是调用修改变量的类的更新方法。另一个调用读取变量的类的更新方法。只有一个线程写入,一个(或多个)线程读取该变量。由于我是多线程新手,我需要在并发方面做什么?
public class A
{
public int variable; // Does this need to be volatile?
// Not only int, could also be boolean or float.
public void update()
{
// Called by one thread constantly
++variable;
// Or some other algorithm
variable = complexAlgorithm();
}
}
public class B
{
public A a;
public void update()
{
// Called by another thread constantly
// I don't care about missing an update
int v = a.variable;
// Do algorithm with v...
}
}
Thanks,
谢谢,
采纳答案by hidralisk
If there is one and only one thread that writes to variable
you can get away with making it volatile
. Otherwise see the answer with AtomicInteger
.
Only volatile
will work in case of only one writing thread because there is only one writing thread so it always has the right value of variable
.
如果只有一个线程向variable
您写信,您就可以避免使用它volatile
。否则请参阅答案AtomicInteger
。
仅volatile
在只有一个写入线程的情况下才有效,因为只有一个写入线程,因此它始终具有正确的 值variable
。
回答by justkt
Not only should variable
be volatile
, but you also want to protect your update
function with some sort of synchronizationsince ++variable
is not an atomic call. It is, after all, just syntactic sugar for
不仅应该variable
是volatile
,而且您还希望通过某种同步来保护您的update
功能,因为它不是原子调用。毕竟,它只是语法糖++variable
variable = variable + 1;
which is not atomic.
这不是原子的。
You should also wrap any calls that read variable in a lockof some sort.
您还应该将任何读取变量的调用包装在某种锁中。
Alternatively, use an AtomicInteger. It was made for this sort of thing (for just integer operations).
或者,使用AtomicInteger。它是为这种事情而制作的(仅用于整数运算)。
public class A
{
// initially had said volatile wouldn't affect this variable because
// it is not a primitive, but see correction in comments
public final AtomicInteger variable; // see comments on this issue of why final
public void update()
{
// Called by one thread constantly
variable.getAndIncrement(); // atomically adds one
}
public int retrieveValue()
{
return variable.get(); // gets the current int value safely
}
}
public class B
{
public A a;
public void update()
{
// Called by another thread constantly
int v = a.retrieveValue();
// Do algorithm with v...
}
}
For the more complex algorithms, as your recent edit assumes, use synchronization or locks.
对于更复杂的算法,正如您最近的编辑所假设的那样,请使用同步或锁。
回答by Jon Freedman
In this case I would use an AtomicInteger, however the generalised answer is that access to variable should be protected by a synchronized block, or by using another part of the java.util.concurrent package.
在这种情况下,我将使用AtomicInteger,但是一般的答案是对变量的访问应该受到同步块的保护,或者通过使用 java.util.concurrent 包的另一部分来保护。
A couple of examples:
几个例子:
Using synchronized
使用同步
public class A {
public final Object variable;
public void update() {
synchronized(variable) {
variable.complexAlgorithm();
}
}
}
public class B {
public A a;
public void update() {
sychronized(a.variable) {
consume(a.variable);
}
}
}
Using java.util.concurrent
使用 java.util.concurrent
public class A {
public final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public final Object variable;
public void update() {
lock.writeLock().lock();
try {
variable.complexAlgorithm();
} finally {
lock.writeLock().unlock();
}
}
}
public class B {
public A a;
public void update() {
a.lock.readLock().lock();
try {
consume(a.variable);
} finally {
a.lock.readLock().unlock();
}
}
}
回答by b_erb
Use AtomicInteger
or synchronize
the access to be safe.
使用AtomicInteger
或synchronize
访问是安全的。