- 好文
- 理解,总结
关于Java并发编程Volatile 关键字讲解最好的一篇文章 | Java面试热门内容精讲之——并发编程volatile (视频) |
---|---|
DMA和cache一致性问题 | DMA导致的CACHE一致性问题解决方案 |
volatile 关键字,你真的理解吗? | 8.volatile为啥不能保证原子性? |
7.volatile怎么通过内存屏障保证可见性和有序性? | 多线程编程中什么情况下需要加 volatile? |
书<<程序员的自我修养>>
视频: 程序员的自我修养视频教程
理解,总结volatile 只能保证可见性,不能保证原子性
两个作用: 1. 阻止编译器对volatile变量指令的重排优化
2. 阻止编译器为了提高速度而将一个变量缓存到寄存器而不写回。
volatile适用于纯赋值 *** 作,如 a = 2 (其经过三步 : 1. load a to register 2. 将寄存器中的值++ 3. 将寄存器中的值写回主存)
注意 : 如 a++ \ a = !a 都不是原子 *** 作,不适用
同步与锁
常用的锁: 二元信号量 、 (多元)信号量、互斥量 、 临界区 、 读写锁、条件变量
先要明白为什么自增不是原子 *** 作
(这里写的汇编指令都简化记不一定是对的,明白意思就行)
原子 *** 作是指: 单指令的 *** 作
如: a = 2 mov a, 2
++a在很多体系上的实现如下:
1.读取a 到某个寄存器X mov X,a
2.X++ add X, 1
3.将X的内容存储回a mov a, X
先讲一下指令重排为什么可以优化速度
重排前:
a = 2; //1. load(加载进寄存器) 2. set(设置为2) 3. store(写回)
b = 4;//1. 2. 3.
a = a + 1;//1. 2. 3.
一共9步 *** 作
重排 :
a = 2;//1.load 2.set 先不写回
a = a + 1;//3. set 4.store
b = 4;//1. 2. 3.
一共7步 *** 作,优化了速度
volatile 如何保证数据的可见性:
volatile修改数值后会将其写回主存,通过总线嗅探机制一旦总线嗅探到某个线程修改了数值,
就将其他线程已经缓存的先前数值做废,重新读取主存内的值,所以可以保证可见性
为什么不能保证原子性:
不能保证原子性的关键在于,读 *** 作的时候,读取到相同的数据,但是在写入时其中某个线程因为阻塞等原因,
存在一种情况,即这个线程的写 *** 作不在另一个线程修改完变量回写时的加锁时间区间,导致这个线程的写 *** 作
覆盖了另一个线程的写 *** 作。
书中精彩片段
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)