我就站在你面前,你却视而不见!
2020-04-15 16:04:43来源:博客园 阅读 ()
我就站在你面前,你却视而不见!
在上一篇文章一男子给对象转账5000元,居然又退还了!中,我们学习了并发三大特性之一的原子性,并对原子性问题进行分析。
这篇文章我们就一起来了解下可见性:
可见性
首先看下可见性的概念:
可见性就是指某一个线程修改了共享变量的值时,其他线程能够立即得知这个修改。
什么?难道变量被修改了,线程不应该马上读取到的吗?为什么和我认知的不一样呢?
好的,那么接下来让我们带着问题,一起来搞懂可见性问题。
可见性问题
可见性问题的元凶就是 CPU 缓存,都怪 CPU 为程序性能优化做的努力,搞出这么多幺蛾子。
关于 CPU 缓存可以阅读:原来 CPU 为程序性能优化做了这么多
首先在单核 CPU 上,是不存在可见性问题的,因为所有的线程都在一个 CPU 上执行,所有的线程都是操作同一 CPU 缓存,某一个线程修改了共享变量的值,另外的线程也可以马上读取到,因此是可见的。
如上图所示,Thread-0
和 Thread-1
都是在一个 CPU 缓存上进行操作,所以 Thread-0
修改了变量 flag
的值后,Thread-1
再去访问变量 flag
,得到的一定是最新的 flag
值。
然而在多核 CPU 上,由于每个 CPU 都有自己的缓存,当多个不同线程运行在不同的 CPU 上时,这些线程操作的 CPU 缓存也是不同的,因此某一个线程对共享变量进行修改时,另外的线程读取到的不一定是最新值,也就不具有可见性了。
如上图所示,Thread-0
是在 CPU-0
上的缓存进行操作,Thread-1
是在 CPU-1
上的缓存进行操作,所以 Thread-0
修改了变量 flag
的值后,Thread-1
再去访问变量 flag
,得到的不一定是最新的 flag
值,因此 Thread-0
对共享变量 flag
的修改对 Thread-1
是不可见的。
下面用一个例子来看下可见性问题,创建一个 VisibilityTest
类,实现 Runnable
接口,在 run()
方法中判断 flag
是否为 true
,若为 true
则进行打印操作,主方法中启动一个线程 thread
,主线程等待 0.5 秒后,将 flag
的值设为 true
。
public class VisibilityDemo {
private static class VisibilityTest implements Runnable {
private boolean flag = false;
@Override
public void run() {
while (true) {
if (flag) {
System.out.println(Thread.currentThread().getName() + ":" + flag);
}
}
}
}
public static void main(String[] args) throws InterruptedException {
VisibilityTest visibilityTest = new VisibilityTest();
Thread thread = new Thread(visibilityTest);
thread.start();
// 等待线程启动
Thread.sleep(500);
// 更新 flag 为 true
visibilityTest.flag = true;
System.out.println(Thread.currentThread().getName() + ":" + visibilityTest.flag);
}
}
发现输出的结果为:main:true
,和我们想象的不太一样,按道理 thread 应该会持续打印出 Thread-0:true
的,但是并非如此,这也就验证了我们刚才讲的可见性问题。
那么如何解决可见性问题呢?
可以采用同步的方式去解决或者使用 volatile 关键字也可以保证可见性。
关于 volatile 相关原理可以阅读:你真的了解 volatile 关键字吗?
总结
本文学习了线程安全三大特性之中的可见性,另外 CPU 缓存在提高程序性能的同时也带来了可见性问题,只有我们理解了可见性的原理,才更容易去诊断并发编程中的 BUG。
参考
《Java并发编程实战》
《深入理解Java虚拟机:JVM高级特性与最佳实践》
《实战Java高并发程序设计》
《Java多线程编程核心技术》
Java并发编程实战
原文链接:https://www.cnblogs.com/wupeixuan/p/12704278.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 站在更高的角度,看微服务架构的理论基础 2019-12-30
- 论Java访问权限控制的重要性 2018-12-02
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash