在Java中,volatile关键字错误

25 浏览
0 Comments

在Java中,volatile关键字错误

这个问题已经有答案了:

什么时候使用volatile关键字有用?

我正在尝试编写一个简单的代码来理解Java中的volatile关键字。

思路是使用两个线程来递增Runner类的count字段的值。Helper类实现了Runnable,在run方法中递增计数,其中count是静态和volatile的。

        class Helper implements Runnable{
            @Override
            public void run() {
                for(int i=0; i<100000;i++){         
                    Runner.count+=1;
                }
            }
        }
        public class Runner {
            public static volatile long count=0; // to be incremented
            public static void main(String[] args){
                Thread t1 = new Thread( new Helper()); 
                Thread t2 = new Thread( new Helper());
                t1.start();
                t2.start();
                try {
                    t1.join();
                    t2.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Count= "+count); // output expected to be 200000
            }
        }

预期的每次运行输出都是Count = 200000,但有时我会得到不同的数字。

请帮助我了解这是如何可能的。

admin 更改状态以发布 2023年5月24日
0
0 Comments

Runner.count+=1;

意思是:

Runner.count = Runner.count + 1;

或者说:

  1. 获取Runner.count的值。
  2. 将该值加1。
  3. 将新值存储在Runner.count中。

线程A和B都可以获取Runner.count的值(因此它们都得到了1),然后同时将1加1(因此它们都得到了2),然后同时将其存储回去(因此新值为2) - 现在该值已经从1变为2,而不是从1变为3,即使两个线程都对其进行了递增!

0
0 Comments

volatile关键字的作用大致是,对该变量的每个独立的读写操作都是原子性的。

然而要注意的是,需要多个读写操作的操作(例如i++,它等同于i = i + 1,执行一次读和一次写)不是原子性的,因为其他线程可能会在读和写之间写入i。

0