繁体   English   中英

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

[英]Atomic operation on read/write variable in java

我有一个 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”,也就是说,我不希望在它们之间共享“num”变量。

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

我知道在 C# 的情况下,它可以使用 lock(object) 来完成,如下所示,但在 java 中我不知道(我是新手):

C# 上的原子操作

您可以同步这些方法,但您可能会发现使用 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);
}
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/

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

在 Java 中,我对使用 volatile 变量表示怀疑,因为 volatile 变量只能在一个线程正在写入而其他读取正在读取时使用。 Volatile 仅在一个线程正在写入时起作用。

“其中一个线程 (T1) 修改计数器,另一个线程 (T2) 读取计数器(但从不修改它),声明计数器变量 volatile 足以保证 T2 写入计数器变量的可见性。

然而,如果 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

暂无
暂无

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

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