Volatile关键字与内存可见性

代码示例:

Volatile关键字与内存可见性_第1张图片不加Volatile关键字时,子线程由于沉睡一秒,可以认为子线程和主线程是同时运行的,主线程把主内存的共享变量读取到了它的工作内存,同时子线程也把主内存的共享变量读取到了它的工作内存,这个时候,两个线程各自执行自己的,互不干扰。子线程虽然在后续执行中,把这个共享变量flag改成了true,并把它刷新回了主内存,但是,主线程在改之前就已经把共享变量读取到了它的工作内存,即读取为false,而主线程中的while循环是个空循环,就只有一个if判断语句,没有其他任何代码(如果有其他的一些代码操作,比如打印操作,是有机会在执行其他操作的间隙中读取被子线程修改过的共享变量,进而结束循环),所以说它循环的速度特别快,并且while循环是java中的底层代码,它的程序的优先度本身就稍微快一点,所以没有一点时间间隙提供给主线程重新的再去把主线程中的更新后的共享变量再读下去,最后while循环就一直在做死循环,结束不了。Volatile关键字在底层做了一些处理,实际上是对java的执行器CPU进行了底层代码级的优化,将我们写的代码变成字节码的形式,再变成汇编的指令集后,进行重排序,使得两个线程之间其中一个对共享变量做了更改的时候,另外一个线程是可见的,并且会把更改后的变量值再重新把它读下来。就会读取被子线程修改过的共享变量,进而结束循环。

内存可见性其实就是共享变量在线程间的可见性

共享变量:如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是共享变量
可见性:一个线程对一个共享变量的修改,能够及时的被其他线程看到

实际上共享变量在线程间常常是看不见的,解决方式:

1.Volatile关键字实现可见性,尤其是嵌入式开发中
2.synchronized实现可见性,
解锁前:必须把共享变量的最新值刷新到主内存中
加锁时:清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新值
缺点:程序效率低,对计算机硬件资源是高开销动作

Volatile关键字与synchronized比较

1.Volatile关键字不需要加锁,比synchronized更轻量级,不会阻塞线程,效率更高
2.从内存可见度讲,Volatile读相当于加锁,Volatile写相当于解锁
3.Volatile不具备”互斥性“,synchronized具备”互斥性“。
4.synchronized既能保证可见性,又能保证原子性。Volatile保证可见性,但能保证原子性
5.如果能用Volatile解决问题,尽量使用Volatile,因为它的效率更高

注:个人学习总结与见解

你可能感兴趣的:(笔记,java)