java并发编程(3)-CPU及JAVA原子操作的实现原

本文深入探讨了CPU实现原子操作的两种主要方式——锁总线和锁缓存,以及现代处理器如何通过缓存锁定来优化原子性操作,减少总线锁带来的性能损耗。此外,文章还介绍了Java中实现原子操作的机制,包括锁和CAS操作,以及CAS操作可能遇到的问题及其解决方案。
摘要由CSDN通过智能技术生成

CPU原子操作实现方式
cpu一般用锁总线或锁缓存的方式实现原子操作。
首先每个cpu可以保证从系统中读取或写入一个字节是原子的。当一个cpu访问内存中一个字节时其他cpu不能访问这个字节。P6以及最新的处理器同一个缓存行里16/32/64位的操作是原子的,但是对于跨总线跨缓存行的数据无法保证访问的原子性,这种数据就需要用总线锁或者缓存锁来实现。
总线锁:所谓总线锁就是使用处理器提供的一个Lock#信号 当一个处理器在总线上输出这个信号其他处理器的请求会被阻塞,即只有这个cpu可以访问共享内存。
缓存锁:总线锁的方式虽然可以实现原子性但是由于阻塞总线,开销比较大,所以现在的处理器在某些场合下会使用缓存锁来替代。频繁使用的内存会被缓存在cpu的高速缓存中,P6和目前的处理器可以使用缓存锁定的方式,实现复杂的原子性。
缓存锁定:如果内存区域在cpu的缓存行中,并且使用了Lock 指令,那么在操作完成时就将结果直接回写到内存,并且不用在总线上声明Lock信号来锁总线。CPU的缓存一致性机制会保证同一时间只有一个cpu更改同一块主内存数据,并且修改完主内存数据后其他cpu的缓存的该数据会失效。这样就避免了锁总线的开销。

两种情况下不能使用缓存锁定:1)有的CPU不支持缓存锁定 2)操作的内容不在CPU缓存中。

java原子操作实现方式
java 中实现原子操作的方式使 锁 和 CAS操作。
CAS操作:JVM的CAS操作利用了 CPU的CMPXCHG指令。通过循环自旋来实现原子性操作。代码示例如下:

AtomicInteger i=0;
for(int i=0;i<10;i++){
	for(;;){
		int ii=i.get();
		boolean succ = i.compareAndSet(ii,++ii);  
		 if(succ)//如果没有修改值成功就重新获取值再次修改不断循环 直到成功为止
		 		break;  
	}
}

CAS问题:
1)ABA问题:cas只是将比较原来的值和传入的期望值是否相同,如果相同则可以修改,如果一个变量由A变为了B然后又编程了A 这个时候我们检查时会认为值没有变,但其实是变了。(感觉这种影响应该不大,毕竟值一样了就不会影响准确性)。解决办法:变量中同时维护一个版本号 每次更新版本号都加1,1A 2B 3A 。
2)自旋消耗CPU,长时间空转会十分消耗CPU 可以设置时间限制
3)只能保证一个共享变量的原子操作。解决 可以尝试将 两个变量组合成一个比如 i=1 j=4 合并成 ij=14

锁机制
java 锁机制保证只有获得了锁的线程才可以操作指定内存,保证了原子性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

catch that elf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值