简体   繁体   English

Java在两个线程之间共享一个变量

[英]Java share a variable between two threads

I have two threads. 我有两个主题。 One invokes the update method of a class that modifies a variable. 一个调用修改变量的类的update方法。 Another invokes the update method of a class that reads the variable. 另一个调用读取变量的类的update方法。 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, 谢谢,

If there is one and only one thread that writes to variable you can get away with making it volatile . 如果有一个且只有一个线程可以写入variable那么可以使它变得volatile Otherwise see the answer with AtomicInteger . 否则请使用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 . 只有一个写线程只有volatile才能工作,因为只有一个写线程,因此它始终具有正确的variable值。

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 ,但是通用的答案是对变量的访问应该由synchronized块保护,或者使用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();
        }
    }
}

Not only should variable be volatile , but you also want to protect your update function with some sort of synchronization since ++variable is not an atomic call. variable不仅应该是volatile ,而且您还希望通过某种同步保护update函数,因为++variable不是原子调用。 It is, after all, just syntactic sugar for 毕竟,它只是语法糖

variable = variable + 1;

which is not atomic. 这不是原子的。

You should also wrap any calls that read variable in a lock of some sort. 您还应该将任何读取变量的调用包装在某种中。

Alternatively, use an AtomicInteger . 或者,使用AtomicInteger It was made for this sort of thing (for just integer operations). 这是为了这种事情(仅用于整数运算)。

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. 对于更复杂的算法,如您最近的编辑所假设,使用同步或锁定。

使用AtomicIntegersynchronize访问是安全的。

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

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