惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Palo Alto Networks Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
阮一峰的网络日志
阮一峰的网络日志
Recent Announcements
Recent Announcements
P
Proofpoint News Feed
H
Hacker News: Front Page
H
Help Net Security
云风的 BLOG
云风的 BLOG
H
Heimdal Security Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
L
Lohrmann on Cybersecurity
C
Check Point Blog
Google DeepMind News
Google DeepMind News
Forbes - Security
Forbes - Security
P
Proofpoint News Feed
Google DeepMind News
Google DeepMind News
I
InfoQ
The GitHub Blog
The GitHub Blog
The Cloudflare Blog
I
Intezer
L
LINUX DO - 最新话题
K
Kaspersky official blog
Attack and Defense Labs
Attack and Defense Labs
C
CERT Recently Published Vulnerability Notes
aimingoo的专栏
aimingoo的专栏
S
SegmentFault 最新的问题
NISL@THU
NISL@THU
人人都是产品经理
人人都是产品经理
雷峰网
雷峰网
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Vercel News
Vercel News
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Threatpost
Y
Y Combinator Blog
S
Security Affairs
Latest news
Latest news
T
Threat Research - Cisco Blogs
T
Tailwind CSS Blog
C
Cisco Blogs
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
P
Privacy International News Feed
Jina AI
Jina AI
Apple Machine Learning Research
Apple Machine Learning Research
Cisco Talos Blog
Cisco Talos Blog
T
Troy Hunt's Blog
S
Securelist
MongoDB | Blog
MongoDB | Blog

博客园 - 一个人的合唱

手写简易docker synchronized 泛型学习 反码与补码 解决128位秘钥长度限制的方法 CAP学习 ThreadLocal的学习 读书笔记脑图列表 a=a++和a=++a centos7下安装python3 深入理解jvm虚拟机笔记(二) AtomicInteger的使用 echarts重新绘制的时候数据未更新 深入理解jvm虚拟机笔记(一) elasticsearch学习笔记 使用fiddler模拟post请求 二叉堆 二叉平衡树 二叉查找树
volatile学习
一个人的合唱 · 2017-11-15 · via 博客园 - 一个人的合唱

原理

编译时,在对volatile变量的赋值操作指令后加个加锁的空操作了强制把修改立即写回主内存,同时其他工作内存往执行引擎中传递被volatile修饰的变量的值时,必须从主内存中获取然后立刻传给工作引擎,这样保证读取到的是最新值,即为内存可见性,另外修改同步回内存,意味着所有之前的操作都已经执行完成,这样便形成了“指令重排序无法越过内存屏障”的效果了。

作用

  • 内存可见性
    • volatile变量对所有线程是立即可见的,对volatile变量所有的写操作都能立刻反应到其他线程之中,只保证了可见性
    • 但同一时间都对该值做了修改的话还是会冲突,也就是说其他线程的修改还来不及在你的操作执行之前通知到你的话,那么修改就会冲突
    • 因此只适用于:
      1. 运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值。
      2. 变量不需要与其他的状态变量共同参与不变约束。
      3. 即所有操作的顺序可以打乱,结果仍一样。
    • 因此,我觉得volatile修饰的变量只保证读一致性,每一个读操作在读时所读到的值确保是最新值,但写就不一定了,如果同时修改且写回主内存时来不及通知其他线程而其他线程的修改也到了主内存,这时便产生了冲突。但volatile的锁是最轻量的,它只在编译时,在对volatile修饰的变量赋值的指令后加个加锁的空操作而不是对该值加锁,那么该变量可以任意读取,且读取到的数据都为最新值,只需忍受同时修改时可能会发生的冲突,有些情况下很值得。
    • 例如如果两条线程要做的操作同样是把原值加上某值,然后恰好同时执行,因为加锁的空操作都立马写回主内存,这是就会产生写冲突,但如果是其中一个线程先执行该指令,之后会立马写回主内存,然后另一条线程执行到该语句,然后去主内存中取值立马交给执行引擎执行,这是就是最新的值却不会产生写冲突。而如果两个线程要做的操作都是把false设置成true,然后因为可见性,其他等待在该状态上的线程会相当于立马得到通知。所以如果只需要读一致性,可以忍受可能发生的写冲突的话,volatile可以提供比同步关键字更好的性能,因为这个可以随便读且读到的值是最新的值。
  • 禁止指令重排序
    • 指令重排序是编译优化的技术一种,例如在条件允许的情况下,直接运行当前有能力立即执行的后续指令,避开获取下一条指令所需数据时造成的等待,但它只保证重排序后线程内表现为串行的语义,即重排序后如果是单线程执行,那么结果一定跟排序前一样。所以重排序后,并行时会发生很多我们之前无法想象的问题。
    • 指令重排序的规则之一是有依赖的语句之间的相对顺序必须得到保证,否则语义会出现错误,然后其他的语句可以自由插入它们之间。加锁的空操作使得修改立即写回主内存,这使得之前所做的操作都已经执行完成,为了达到storeload屏障,后面的指令无法重排序到该加锁空操作之前,因此该加锁空操作就像个内存屏障。