如果觉得我的文章还不错的话就点个赞,关注一波,转发收藏吧,另外可以微信搜索【佘凡架构师】阅读更多的好文章,获取我为大家准备的资料。
Java内存模型中原子性,有序性,可见性是个什么东西?
一般我们在并发编程中,会产生三类问题,原子性,有序性,可见性。
原子性
原子性表示线程在操作变量时,要不全部成功,要不全部失败,没有中间状态。也就是说现在有两个线程,线程A,线程B。线程A在对data变量做++(或者其他)操作的时候,线程B是没有办法影响到线程A的这个操作。只有当线程A做完了这个操作之后,线程B才能够对data变量做其他的操作。
但是比较遗憾的是,因为在多线程中,线程操作都是都是工作内存中的变量数据,在这种线程隔离的情况下,是不具备原子性的。也就是说线程A跟线程B是同时可以操作data变量。如线程A在对data变量做“++”操作的时候,线程B同样可以对data变量做“++”操作。所以我们需要借助其他的方式来保证原子性。
可见性
在我的一篇图文搞定Java内存模型 中画图演示了可见性问题。就是当线程A对data变量做修改的时候,其他线程在操作data变量时能够及时的发现这个数据已经被改过了,需要重新读取新的data变量再操作,反之亦然。
有序性
有序性指的是从源代码到编译运行的过程中,会有多种重排序的指令发生。重排序的目的是为了更快的去执行代码,提高代码效率。但是在多线程的情况下,胡乱的重排序会导致最终的运行结果跟原始代码运行的结果不一样。这样的代码部署到生产环境很容易造成重大事故。而有序性就是为了解决这种问题,禁止重排序来保证程序的顺序执行。
现在有代码块1跟代码块2,代码块1经过重排序后,运行的结果跟未经过重排序的结果一致。但是代码块2经过重排序后,运行 int b = a - 5就会报错,因为在此之前变量a都没有被申明。所以这种代码经过重排序会部署到生产环境会出现重大事故。
再看一下下面的例子,若线程A跟线程B同时运行,一旦调整了线程A的操作1与操作2,那么在线程B中的执行逻辑完全会改变,也就不会进入到if(flag){ int i = a * a }的代码块中,也就会影响最终的执行结果。