开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
可见性
可见性概念
可见性(Visibility):是指一个线程对共享变量进行修改,另一个先立即得到修改后的新值。
1.当没有加Volatile的时候,while循环会一直在里面循环转圈 2.当加了之后Volatile,由于可见性,一旦num改了之后,就会通知其他线程 3.还有注意的时候不能用if,if不会重新拉回来再判断一次。(也叫做虚假唤醒) 4.案例演示:一个线程对共享变量的修改,另一个线程不能立即得到新值
如下图:
由上面代码可以看出,并发编程时,会出现可见性问题,当一个线程对共享变量进行了修改,另外的线程并没有立即看到修改后的最新值。
原子性
原子性概念
原子性(Atomicity):在一次或多次操作中,要么所有的操作都成功执行并且不会受其他因素干扰而中 断,要么所有的操作都不执行或全部执行失败。不会出现中间状态
原子性演示
案例演示:5个线程各执行1000次 i++;
volatile不保证原子性的代码验证
1、控制台输出:(由于并发不安全,每次执行的结果都可能不一样)
20个线程执行完之后num: 19706
正常来说,如果保证原子性的话,20个线程执行完,结果应该是20000。控制台输出的值却不是这个,说明出现了原子性的问题。
2、使用javap反汇编class文件,对于num++可以得到下面的字节码指令:
由此可见num++是由多条语句组成,以上多条指令在一个线程的情况下是不会出问题的,但是在多线程情况下就可能会出现问题。
比如num刚开始值是7。A线程在执行13: iadd时得到num值是8,B线程又执行9: getstatic得到前一个值是7。马上A线程就把8赋值给了num变量。但是B线程已经拿到了之前的值7,B线程是在A线程真正赋值前拿到的num值。即使A线程最终把值真正的赋给了num变量,但是B线程已经走过了getstaitc取值的这一步,B线程会继续在7的基础上进行++操作,最终的结果依然是8。本来两个线程对7进行分别进行++操作,得到的值应该是9,因为并发问题,导致结果是8。
3、并发编程时,会出现原子性问题,当一个线程对共享变量操作到一半时,另外的线程也有可能来操作共 享变量,干扰了前一个线程的操作。