Java并发三大特性(可见性、有序性、原子性)

可见性

问题

每个线程读取r会在内存中拷贝到自己线程使用的缓存中,当其中一个线程改变r值,另外一个线程是感知不到的。
在这里插入图片描述

解决办法

volatile保证可见性

CPU缓存体系

在这里插入图片描述

缓存行

cacheLine:因为程序局部性原理,按快读取,可以提高效率。一般64字节。

伪对齐:线程读取到自己不需要数据,而且要为不需要的数据同步花费时间,执行效率底下。
解决:@Contended缓存行对齐,避免伪对齐。

在这里插入图片描述

硬件保证缓存一致性

缓存一致性协议,保证线程之间缓存内容一致。
Intel: MESI一致性协议,cpu每个cache line标识4中状态(修改,共享,独占,无效)。

有序性

问题

大家都知道cpu执行没有前后依赖的指令是乱序执行的,当然java在执行字节码指令也是乱序的,只要保证单线程情况下输出结果是一致就可以。这样可以极大的提升执行效率。

但是也有一些问题:在多线程情况会出问题的。下面举一个对象半初始化的例子。

Object o=new Object();

字节码指令:
在这里插入图片描述
有肯能在执行new开辟内存空间后,就先去执行astore指令,告诉别的线程对象已经初始化完毕,但是执行初始化方法的指令还有调用,导致对象的数据错误。

原子性

问题

多线程条件下访问共享数据时候,产生竞争,导致数据不一致;需要线程同步保证数据一致。

n++(不是原操作): 1.读取数据 、2.加1 、3.赋值写会内存

解决

悲观锁

synchronized保证原子性: 本质(并发编程序列化)

monitor(管程):锁
临界区:锁的代码段,也就是锁的粒度。

synchronized可以保证可见性,加锁解锁会和内存进行同步。

乐观锁

CAS自旋锁

AtomicInteger使用CAS保证原子性。

在这里插入图片描述

Hostpot源码:
在这里插入图片描述

使用指令lock cmpcxg指令,但是这条指令也不是原子性的,使用lock锁实现的。在这里插入图片描述

使用场景

synchronized:临界区比较大,等待人多。
CAS自旋锁:等待人少。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值