java中读/写变量的原子操作

时间:2016-02-10 12:07:24

标签: java multithreading thread-safety locking atomic

我有一个java类,如下所示:

public class Example implements Runnable {

    private int num;

    ...

    // Getter
    public int getNum(){
        return this.num;
    }

    // Setter    
    public void addToNum(int amount) {

        if (this.amount> 0) {
            this.num += amount;
        }
    }

    ...
}

此类可以由多个线程实例化。每个实例都有自己的“数字”,也就是说,我不想要#num;#39;变量将在所有它们之间共享。

对于每个实例,可以在concurreny中访问多个线程,以便读/写' num'变量。那么什么是保护' num'的读/写操作的最佳选择。变量,以便它们是原子操作?

我知道在C#的情况下,可以使用像下面的链接一样使用锁(对象)但在java中我不知道(我是新的):

Atomic operations on C#

4 个答案:

答案 0 :(得分:4)

您可以同步方法,但您可能会发现使用AtomicInteger更快的选项。

private final AtomicInteger num = new AtomicInteger();

...

// Getter
public int getNum(){
    return this.num.get();
}

// Setter    
public void addToNum(int amount) {
    if (amount > 0) {
        this.num.getAndAdd(amount);
    }
}

这两种方法都是无锁的,并且避免暴露可能以非预期方式使用的锁。

在Java 8中,getAndAdd使用单个机器代码指令通过Unsafe类添加。来自AtomicInteger

private volatile int value;

public final int get() {
    return value;
}
public final int getAndAdd(int delta) {
    return unsafe.getAndAddInt(this, valueOffset, delta);
}

答案 1 :(得分:1)

public synchronized void addToNum(int amount) {

    if (this.num > 0) {
        this.num += amount;
    }
}

在这里,您将找到它的文档 http://www.programcreek.com/2014/02/how-to-make-a-method-thread-safe-in-java/

答案 2 :(得分:0)

您可以使用synchronized,阅读它。您可以同步方法。

答案 3 :(得分:0)

在Java中,我对使用volatile变量表示怀疑,因为volatile变量仅在一个线程正在写入而其他读取正在读取时才可以使用。仅当一个线程正在写入时,挥发才有效。

”,其中一个线程(T1)修改了计数器,而另一个线程(T2)读取了计数器(但从未修改过),声明计数器变量为volatile就足以保证对T2的可见性。 / p>

但是,如果T1和T2都在增加计数器变量,那么仅声明计数器变量volatile是不够的。稍后再说。”

链接:http://tutorials.jenkov.com/java-concurrency/volatile.html#:~:text=The%20Java%20volatile%20keyword%20is%20intended%20to%20address%20variable%20visibility,read%20directly%20from%20main%20memory