volatile 可见性与原子性

321 阅读2分钟

git地址:github.com/fw103699437…

不具有原子性

public class NotAtomicDemo {
    volatile static int k;
//    static int k = 0;
    public static void main(String[] args) {
        int num = 100000;
        CountDownLatch countDownLatch = new CountDownLatch(num);
        for (int i = 0; i < num; i++) {
            new Thread(()->{
                k++;
                countDownLatch.countDown();
            }).start();
        }


        try {
            countDownLatch.await();
            System.out.println(k);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
99994
显然volatile不具有原子性,这个不用多说
Process finished with exit code 0

具有可见性

public class VisibilityDemo {
    static int k = 0;
//    volatile static int k = 0;

    public static void main(String[] args) {
        new Thread(()->{
            while (true){
                if(k>=5){
                    System.out.println("______________k可见了" + new Date(System.currentTimeMillis()) +"           " +  k);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        new Thread(()->{
            while(true){
                k++;
                System.out.println("k++" + new Date(System.currentTimeMillis()) + "    " + k);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}
k++Thu Dec 05 18:12:34 CST 2019    1
k++Thu Dec 05 18:12:35 CST 2019    2
k++Thu Dec 05 18:12:36 CST 2019    3
k++Thu Dec 05 18:12:37 CST 2019    4
k++Thu Dec 05 18:12:38 CST 2019    5
k++Thu Dec 05 18:12:39 CST 2019    6
k++Thu Dec 05 18:12:40 CST 2019    7
k++Thu Dec 05 18:12:41 CST 2019    8
k++Thu Dec 05 18:12:42 CST 2019    9
k++Thu Dec 05 18:12:43 CST 2019    10

说明第一个线程没有意识到k已经>=5了,而且过了很久都没有意识到,多次实验均如此,

加上volatile之后

//    static int k = 0;
    volatile static int k = 0;
k++Thu Dec 05 18:15:07 CST 2019    1
k++Thu Dec 05 18:15:08 CST 2019    2
k++Thu Dec 05 18:15:09 CST 2019    3
k++Thu Dec 05 18:15:10 CST 2019    4
k++Thu Dec 05 18:15:11 CST 2019    5
______________k可见了Thu Dec 05 18:15:11 CST 2019           5
______________k可见了Thu Dec 05 18:15:12 CST 2019           6
k++Thu Dec 05 18:15:12 CST 2019    6
______________k可见了Thu Dec 05 18:15:13 CST 2019           7
k++Thu Dec 05 18:15:13 CST 2019    7

第一个线程可以意识到k>5了,多次试验均是如此。

还有一些没想明白的问题

            while (true){
                //加上之后k居然可见了
                System.out.println("sout");
                if(k>=5){

在while和if之间加上一句之后,在五秒后,第一个线程就可以看到k更新了,,多次实验均如此

                if(k>=5){
                    System.out.println("______________k可见了" + new Date(System.currentTimeMillis()) +"           " +  k);
                    //拿到if外 也可见

                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

或者把sleep放到if外,五秒后,第一个线程也可以看到k更新,多次实验均如此

这就有点想不通了。

结论

虽然有想不通的地方,不过在原子性,可见性上还是有一些收获的,volatile可以立即看到新的值(可见性),但是不具有原子性。