Java 在原子变量上使用volatile

Java 在原子变量上使用volatile,java,multithreading,concurrency,volatile,Java,Multithreading,Concurrency,Volatile,在变量上使用volatile可以降低内存一致性错误的风险(如果这表明我对任何相关概念的理解存在漏洞,请纠正我)。因此,在下面的示例中,即使变量c1是易失性的,但内存恒定性错误的发生仍然会导致c1在输出中变为15或有时变为14,而不是正确的输出16 class Lunch implements Runnable { private volatile long c1 = 0; private Object lock1 = new Object(); private Obje

在变量上使用volatile可以降低内存一致性错误的风险(如果这表明我对任何相关概念的理解存在漏洞,请纠正我)。因此,在下面的示例中,即使变量c1是易失性的,但内存恒定性错误的发生仍然会导致c1在输出中变为15或有时变为14,而不是正确的输出16

class Lunch implements Runnable {

    private volatile long c1 = 0;
    private Object lock1 = new Object();
    private Object lock2 = new Object();
    public void inc1() {
       // synchronized(lock1) { c1 is volatile
            c1++;
       // }
    }

    public void run() {
        try {
            inc1();
            Thread.sleep(1000);
            inc1();
            Thread.sleep(1000);
            inc1();
            Thread.sleep(1000);
            inc1();
            inc1();
            Thread.sleep(1000);
            inc1();
            Thread.sleep(1000);
            inc1();
            Thread.sleep(1000);
            inc1();
        }
        catch(InterruptedException e) {
            return;
        }
    }
    public long value() {
        return c1;
    }
    public static void main(String args[]) throws InterruptedException {
        Lunch l = new Lunch();
       Thread t1 = new Thread(l);
       Thread t2 = new Thread(l);
       t1.start();
       t2.start();
       t1.join();
       t2.join();
       System.out.println(l.value());
    }
} 

你说得对。因为++不是一个原子操作,所以当一个线程与另一个线程同时读取/递增/写入一个值时,仍然可以得到不一致的结果


考虑在这种情况下使用AtomicInteger。

检查以了解volatile的作用。它避免了中间线程缓存,但无论如何,读取其值并在非原子操作中进行更新可能会导致丢失的更新。

原子性只是问题的一部分。还有能见度。如果更改了非易失性(和非同步)变量值,则不能保证其他线程能够及时看到更改,或者根本看不到更改。

这里的假设是++是原子的。验证你的假设!(我有点担心你使用短语“降低风险”。通常目的是确保没有任何风险。)因此,如果我用另一个函数更新(long c1){this.c1=c1}替换run()中多次调用increment()。然后,由于c1是易失性的,并且不涉及++,因此结果应该是一致正确的?或者在加载操作存储操作很少的某些情况下,
AtomicIntegerUpdater
。@msk这将是“正确的”,因为在任何时间点,任何读取c1的线程都可以确保看到c1的最新值。未经事先检查而设置的信息的有用性常常令人怀疑。通常的用例是一个布尔标志,其中一个线程向另一个线程发送信号(如停止标志)。这几乎是我使用volatile的唯一情况。