java源码学习(java-src)之原子性、可见性、有序性到底说的是啥?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java源码学习(java-src)之原子性、可见性、有序性到底说的是啥?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3707字,纯文字阅读大概需要6分钟。
内容图文
![java源码学习(java-src)之原子性、可见性、有序性到底说的是啥?](/upload/InfoBanner/zyjiaocheng/615/c2ad507cec564b10ba07a6a0bb39b88e.jpg)
如果内容有错误或者您有不同的见解,请关注我。想要思维导图的小伙伴们记得留言哦。
项目源码以及脑图链接地址:https://mp.weixin.qq.com/s/6YBVyOeqs_6dx4uGdHvPHw
【问题】为啥出现这三个名词?
因为:现在计算机处理数据可以并发,也就会出现多个线程操作一个数据(代码块)的情况。多核CPU在处理数据的时候会将内存的数据复制到高速缓存中,然后再处理数据,处理之后在写回到主内存中。各个线程都复制了一份数据,又写回内存,内存的数据自然就会有可能变得不一致。比如A线程获取a的值放在自己的内存中,改了一下,还没放回到主内存时,B也读取了a,也操作了。此时A放回去,之后B不知道A刚刚修改了。这三个改变都是基于多线程的,也就说在多线程下会有这三个问题要解决。
原子性(Atomicity)是多线程之间保证只能有一个线程在同一个时间执行。
【释义】一个或多个操作,要么全部执行且在执行过程中不被任何因素打断,要么全部不执行。
这句话经常见但是你会发现,什么是一个或多个操作,理解起来比较费劲,无非就是读写数据嘛,其实如果说我们在读写一个数据的时候,这个读写实际上是两个操作(读和写),那么原子性就是两个操作一块执行,我读了就是我写,你读了我就不写了或者连读也不读。像java源码中:AtomicInteger能保证int这个值的原子性,而synchronize{int a,String b}能保证整个代码块的原子性。
可见性(Visibility)是多线程之间保证变量可以相互读写
【释义】当一个线程修改了变量的值,其他线程能够立即获取到修改之后的值。就是说线程A修改了一个变量之后,线程B马上读取应该就能拿到最新的值。怎么保证这个可见性呢?使用volatile、synchronized、lock、atomicXXX类来保证。
【volatile】
线程在读取数据的时候,不是从缓存中读取了,而是直接从内存(共享内存)中读取这个值。也就是说被volatile修饰的变量在内存中所有的线程在使用时是先读,都不在去缓存一份副本。
【注意】
volatile只能保证可见性,不能保证原子性。读取块,但是写的时候慢(需要执行内存屏障指令,防止指令重排序。
【synchronized】
这货也可以保证可见性,在加锁时清空工作内存的共享变量的值,从而从内存中重新读取共享变量的值。在解锁时需要将工作内存中的共享变量的值写入到主内存。来保证主内存中的数据都是最新的,同时也保证了可见性。
【Lock】
这货为啥能保证可见性呢?因为该类继承了AbstractQueuedSynchronizer,这个类中使用的是state这个变量,而这个变量是volatile 修饰的。
/**
* The synchronization state.
*/
private volatile int state;
【指令重排序】
指令重排序不会破坏依赖关系,它会保证执行结果总是一样。指令重排序是在多线程执行程序时为了提高CPU使用率才会去优化和重排序指令(代码)。
我们在使用volatile修饰的变量的时候,这个代码执行到此处,会先去主内存(共享内存)中读取数据,然后在继续操作,同理synchronized也会防止指令重排序。
为什能防止指令重排序呢?
我觉得就是因为我们在读取volatile修饰的变量的时候是从主内存读取的,而不是自己的线程副本中,在使用该变量时CPU不知道当前值的内容或者已被通知该值已经改变,所以不能重排序。
有序性(orderly)是多线程之间在在执行同一个代码的时候有顺序
【释义】程序按照先后顺序执行,就是说代码在多个cpu上执行,要按照一定顺序执行,A线程执行到此处,其他的线程就得等着A执行完才能执行,就是让代码有顺序的执行。别瞎搞。
【理解】CPU重排序其实是最大利用CPU的资源,不能让CPU闲着,但是如果你让CPU能按照顺序执行,CPU的资源肯定会浪费,因为没有拿到锁的线程都睡着呐。
synchronized保证了有序性(根据as-if-serial语义(就好像是顺序执行一样),无论编译器和处理器怎么优化也好,重排序指令也好,单线程结果一定是正确的。)有了这个sync整个世界都是顺序的,乖的很。
其他说明:
可见性:缓存一致性协议
当CPU对变量进行写操作时发现,变量是共享变量,那么就会通知其他CPU中将该变量的缓存行设置为无效状态。当其他CPU在操作变量时发现此变量在的缓存行已经被设置成了无效,那么就会去主内存中重新读取最新的变量。
内存屏障:一组CPU指令,用于实现对内存操作的顺序限制。
Java编译器,会在生成指令系列时,在适当的位置会插入内存屏障来禁止处理器对指令的重新排序。
如果内容有错误或者您有不同的见解,请关注我。想要思维导图的小伙伴们记得留言哦。
项目源码以及脑图链接地址:https://mp.weixin.qq.com/s/6YBVyOeqs_6dx4uGdHvPHw
内容总结
以上是互联网集市为您收集整理的java源码学习(java-src)之原子性、可见性、有序性到底说的是啥?全部内容,希望文章能够帮你解决java源码学习(java-src)之原子性、可见性、有序性到底说的是啥?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。