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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 01:17:04  来源:igfitidea点击:

Java share a variable between two threads

javamultithreadingconcurrency

提问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 variableyou can get away with making it volatile. Otherwise see the answer with AtomicInteger.

Only volatilewill 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 variablebe volatile, but you also want to protect your updatefunction with some sort of synchronizationsince ++variableis not an atomic call. It is, after all, just syntactic sugar for

不仅应该variablevolatile,而且您还希望通过某种同步来保护您的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 AtomicIntegeror synchronizethe access to be safe.

使用AtomicIntegersynchronize访问是安全的。