码迷,mamicode.com
首页 > 编程语言 > 详细

禁止指令重排序

时间:2020-12-18 13:23:26      阅读:4      评论:0      收藏:0      [点我收藏+]

标签:不一致   修改   允许   表示   缓存   共享   volatil   模型   协议   

volatile总结

简介

volatile是Java中的关键字,用来修饰变量,保证了内存可见性,也就是说其他线程看到总是最新值,禁止指令重排序,保证读写的原子性,不包证复合操作原子性。

Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方便。如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的。

happens-before规则对于volatile有所规定:对volatile变量的写happens-before于对这个变量的写后读。

内存可见性

这个先从CPU的缓存说起,为了提高运行效率,在CPU中由L1,L2,L3三级缓存,每当线程取数据时都会先从缓存中读取,缓存中没有再去主存查找,这就造成一个问题,如果说缓存中的值是旧值,但是线程本身并不知道这个是旧值也不知道是否被修改过,那这就会有问题了,数据不一致。为此提出了一种解决方案,就是MESI缓存一致性协议MESI分别对应的是

  • M(modified)表示此变量已被修改
  • E(Exclusive)表示此变量为独占
  • S(Shared) 表示此变量是共享变量
  • I(Invalid)表示此变量已失效

通过这个协议可以做到线程每次读取的值总是最新的

禁止指令重排序

为了程序的运行效率,编译器、处理器会对指令做出重排序。使用volatile的变量可以禁止指令重排序,以防止对运行结果造成影响。具体实现是内存屏障,分别有

  • loadload
  • loadstore
  • storeload
  • storestore

通过这些就可以达到禁止指令重排

读写操作原子性

变量读写的过程是分步骤的,volatile修饰的可以使读写操作变为原子性

与synchronized区别

volatile保证内存可见性、禁止指令重排序,而synchronized可以保证可见性、线程安全,但不会禁止指令重排序,因此在双重检查法单例模式中用到了volatile,防止返回时变量还没有被赋值。

禁止指令重排序

标签:不一致   修改   允许   表示   缓存   共享   volatil   模型   协议   

原文地址:https://www.cnblogs.com/clion/p/14131750.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!