简体   繁体   English

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

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

I have a java class as below:我有一个 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;
        }
    }

    ...
}

This class can be instantiated by multiple threads.这个类可以被多个线程实例化。 Each of this instances have its own 'num', that is, I do not want 'num' variable to be shared between all them.每个实例都有自己的“num”,也就是说,我不希望在它们之间共享“num”变量。

To each instance, multiple threads can be accessed in concurreny in order to read/write 'num' variable.对于每个实例,可以同时访问多个线程以读取/写入 'num' 变量。 So what is the best option to protect read/write operations on 'num' variable in order to they are atomic operations?那么保护对“num”变量的读/写操作以便它们是原子操作的最佳选择是什么?

I know that in case on C# it can be done using lock(object) like below link but in java I have no idea (I am new on it):我知道在 C# 的情况下,它可以使用 lock(object) 来完成,如下所示,但在 java 中我不知道(我是新手):

Atomic operations on C# C# 上的原子操作

You can synchronized the methods, but you might find using AtomicInteger a faster option.您可以同步这些方法,但您可能会发现使用 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);
    }
}

Both of these methods are lock-less and avoid exposing a lock which could be used in an unintended way.这两种方法都是无锁的,可以避免暴露可能以意外方式使用的锁。

In Java 8, the getAndAdd uses a single machine code instruction for the addition via the Unsafe class.在 Java 8 中, getAndAdd使用单个机器代码指令通过 Unsafe 类进行添加。 From AtomicIntegerAtomicInteger

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

here you'll find documentation for it http://www.programcreek.com/2014/02/how-to-make-a-method-thread-safe-in-java/在这里你会找到它的文档http://www.programcreek.com/2014/02/how-to-make-a-method-thread-safe-in-java/

You can use synchronized , read about it.您可以使用 synchronized ,阅读它。 You can synchronized methods.您可以同步方法。

In Java ,I doubt about using volatile variables because volatile variables can used only when one thread is writing and other reads are reading.在 Java 中,我对使用 volatile 变量表示怀疑,因为 volatile 变量只能在一个线程正在写入而其他读取正在读取时使用。 Volatile works only when one thread is writing . Volatile 仅在一个线程正在写入时起作用。

"where one thread (T1) modifies the counter, and another thread (T2) reads the counter (but never modifies it), declaring the counter variable volatile is enough to guarantee visibility for T2 of writes to the counter variable. “其中一个线程 (T1) 修改计数器,另一个线程 (T2) 读取计数器(但从不修改它),声明计数器变量 volatile 足以保证 T2 写入计数器变量的可见性。

If, however, both T1 and T2 were incrementing the counter variable, then declaring the counter variable volatile would not have been enough.然而,如果 T1 和 T2 都在增加计数器变量,那么声明计数器变量 volatile 是不够的。 More on that later."稍后再谈。”

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