为什么这个java程序的输出除了一个?;

为什么这个java程序的输出除了一个?;,java,concurrency,Java,Concurrency,我正在编写一些代码来模拟CAS(比较和交换)。 这里我有一个方法cas来模拟cas指令,一个方法将增加到+fieldcount1。我启动两个线程,每个线程添加字段count10000次。 问题是,预期产量是20000,但实际产量比20000稍小。例如199841999219989…每一次都是不同的。 如果你能帮助我,我将非常感激 public class SimulateCAS { private volatile int count; private synchronized

我正在编写一些代码来模拟CAS(比较和交换)。
这里我有一个方法
cas
来模拟cas指令,一个方法
增加到+field
count
1。我启动两个线程,每个线程添加字段
count
10000次。
问题是,预期产量是20000,但实际产量比20000稍小。例如199841999219989…每一次都是不同的。
如果你能帮助我,我将非常感激

public class SimulateCAS {
    private volatile int count;

    private synchronized int cas(int expectation, int newValue) {
        int curValue = count;
        if (expectation == curValue) {
            count = newValue;
        }
        return curValue;
    }

    void increase() {
        int newValue;
        do {
            newValue = count + 1;                       // ①
        } while (count != cas(count, newValue));        // ②
    }

    public static void main(String[] args) throws InterruptedException {
        final SimulateCAS demo = new SimulateCAS();
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                demo.add10k();
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                demo.add10k();
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(demo.count);
    }
}
公共类模拟器{
私有可变整数计数;
专用同步int-CA(int-expectation,int-newValue){
int曲线值=计数;
if(期望值==曲线值){
计数=新值;
}
返回曲线值;
}
空隙增加(){
int新值;
做{
newValue=count+1;//①
}while(count!=cas(count,newValue));//②
}
公共静态void main(字符串[]args)引发InterruptedException{
最终SimulateCAS演示=新SimulateCAS();
线程t1=新线程(()->{
对于(int i=0;i<10000;i++){
demo.add10k();
}
});
线程t2=新线程(()->{
对于(int i=0;i<10000;i++){
demo.add10k();
}
});
t1.start();
t2.start();
t1.join();
t2.连接();
System.out.println(demo.count);
}
}

问题在于您的
增加方法

count
的值可以在带有注释的行之间的任意点更新① 及②.
您的
增加
的实现假定这不会发生,并且
计数
在一行中① 与第行中的计数相同②.

一个更好的实现方法是

void increase() {
    int oldValue, newValue;
    do {
        oldValue = count;  // get the current value
        newValue = oldValue + 1; // calculate the new value based on the old
    } while (oldValue != cas(oldValue, newValue)); // Do a compare and swap - if the oldValue is still the current value, change it to the newValue, otherwise not.
}

您的完整代码具有真正的CAS,因此不需要锁。

这不是问题,但是
add10k
不应被称为“add10k”,因为该函数没有添加10k。它应该被称为
increment
或类似的东西。你是对的。谢谢你的建议。我想问题出在两行之间① 和线②, 但我无法解释和解决它。谢谢你的回答!每次使用
count
都是自己读取的。因此,如果该值在1和2之间更改,则可能会错过更新。