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

时间:2010-08-16 13:49:58

标签: java multithreading concurrency

我有两个主题。一个调用修改变量的类的update方法。另一个调用读取变量的类的update方法。只有一个线程写入,一个(或多个)线程读取该变量。在并发方面我需要做什么,因为我不熟悉多线程?

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

谢谢,

4 个答案:

答案 0 :(得分:17)

如果只有一个线程可以写入variable,那么您可以将其设为volatile。否则请使用AtomicInteger查看答案。

只有一个写作线程,只有volatile才有效,因为只有一个写线程,所以它始终具有正确的variable值。

答案 1 :(得分:9)

在这种情况下,我会使用AtomicInteger,但是通用的答案是对变量的访问应该由synchronized块保护,或者使用java.util.concurrent包的另一部分。

几个例子:

使用已同步

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

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

答案 2 :(得分:8)

variable不仅应该volatile,而且还希望用some sort of synchronization保护update函数,因为++variable不是原子调用。毕竟,它只是

的语法糖
variable = variable + 1;

这不是原子的。

您还应该将任何读取变量的调用包装在某种lock中。

或者,使用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...
    }
}

对于更复杂的算法,正如您最近的编辑所假设的那样,使用同步或锁定。

答案 3 :(得分:4)

使用AtomicIntegersynchronize访问是安全的。