java-锁-volatile

锁和volatile

锁的特性:原子性、可见性

volatile的特性:可见性

原子性:一次只允许一个线程使用共享数据。

可见性:保证共享变量对所有线程的可见性,当一个线程修改了共享变量的值,新值能立即同步到主内存,其它线程每次使用前立即从主内存刷新。

volatile的作用,可见性 + 禁止指令重排序优化。

Happens-Before六大规则

作用:某个线程修改的变量何时对其他线程可见。

1、程序的顺序性原则

单线程程序前面对某个变量的修改一定对后续操作可见。

2、volatile变量规则

对于一个volatile变量,写操作 Happens-Before 后续的读操作。

3、传递性规则

A Happens-Before B,且 B Happens-Before C,那么A Happens-Before C。

4、管程(synchronized)中锁的规则

对于一个锁,解锁 Happens-Before 后续加锁,所以synchronized加锁解锁会刷新内存。

5、线程start()规则

子线程start()后,子线程中能看到start()前的变量。

6、线程join()操作

主线程 A 等待子线程 B 完成(主线程 A 通过调用子线程B 的 join() 方法实现),当子线程 B 完成后(主线程 A 中 join() 方法返回),主线程能够看到子线程的操作。

重排序

1、编译器重排序。编译器在不改变单线程程序语义的前提下,可以对语句乱序执行。

2、指令重排序。为了提高执行效率,CPU可以乱序执行。

3、缓存的读和写,看上去像是在乱序执行。

内存屏障

【内容有误,待改】

(1)内存屏障的作用:

  1. 阻止屏障两侧的指令重排序;
  2. 强制把主存数据更新到本地缓存,和把写缓存区数据写回主存。

(2)两种屏障:

  • Load Barrier:在指令前插入Load Barrier,加载数据时会强制从主存加载数据。
  • Store Barrier:在指令后插入Store Barrier,会让写入缓存中的数据更新写入主存。

(3)java的内存屏障更细致,分为四种:

屏障类型指令示例说明
LoadLoad BarrierLoad1;LoadLoad;Load2确保Load1装载先于Load2及后续装载
StoreStore BarrierStore1;StoreStore;Store2确保Store1写入先于Store2及后续写入
LoadStore BarrierLoad1;LoadStore;Store2确保Load1装载先于Store2及后续写入
StoreLoad BarrierStore1;StoreLoad;Load2确保Store1写入先于Load2及后续装载
它会使屏障前的(加载和写入指令)完成后,才执行屏障之后的(加载和写入指令)。
这个屏障是个万能屏障,兼具其它三种内存屏障的功能,它的开销是四种屏障中最大的。

(4)volatile 的内存屏障策略非常严格保守,任何指令都不能重排序:

  • 在每个volatile写操作前插入StoreStore屏障,在写操作后插入StoreLoad屏障;
  • 在每个volatile读操作前插入LoadLoad屏障,在读操作后插入LoadStore屏障;

上面概括为:SS,写,SL、LL,读,LS

也可以这样:LS,写,SS、SL,读,LL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值