
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
Java编程开发技术是目前大多数软件开发程序员都在学习的一个编程开发语言,而本文我们就通过案例分析来简单了解一下,Java编程原子操作实现方法分享。
原子的本意即“不能被进一步分割的小粒子”,自然,原子操作即是一个或一组不可被中断的操作。对于并发程序来说,原子操作,或者说原子性是一种极为重要的特性。
处理器实现原子操作
处理器本身就可以实现一些基本操作的原子性:即当处理器从内存中读或写一个字节时,该操作是必然原子的。
而涉及到缓存的一些复杂内存操作就无法保证其原子性,这种情况下,处理器提供两种机制来保证内存操作的原子性:
总线锁定
缓存锁定
其实之前Volatile的部分我们就聊过这两种机制了,总线锁定就是LOCK#信号。该信号会暂时阻塞一切CPU针对总线输出信号的请求,简单粗暴且开销巨大。
而缓存锁定就是lock前缀的一行汇编指令,会强行要求处理器对该数据存在的高速缓存行进行一次内存写回,通过CPU的缓存一致性机制来阻止其他进程针对其进行操作,从而保证我们的操作的原子性。
但是要注意,缓存锁定在以下两种情况下是不适用的:
当操作的数据不能被换存在处理器内部,或者是操作的数据跨多个缓存行时,处理器会调用总线锁定来实现原子操作
有些处理器并不支持缓存锁定
Java实现原子操作
讲完了处理器,来看看Java如何实现原子操作。Java正如前面所说,有两大实现原子操作的方法
CAS操作
锁机制
先是利用CAS操作,思路很简单,自旋的针对一个变量进行CAS操作,直到成功为止,成功以后我们知道,由于硬件限制,其他处理器无法操作这一缓存对应的内存区域,从而实现了原子性。
CAS操作虽然相对锁更轻便,但还是有如下缺点:
ABA问题
即CAS核心在于将栈帧中的E(预期值)与内存中的V(实际值)比对,若相等则进行计算值的替换,但是这里问题在于,判断值是否相等,不等于判断该值是否变动过。即,也有可能该值经历了从A变成B,继而又变成了A,但终CAS却判定相等了,那么这就是不对的。
JDK1.5时,AtomicStampedReference类的compareAndSet()方法就解决了这个问题,它会先判断当前引用是否等于预期引用,也就是值有没有变,再判断当前标志是否等于预期标志,也就是有没有被改动过,这样就规避了ABA问题
自旋时间长开销大
由于CAS操作如果对比不成功,就会自旋地继续读取内存中的新值再度尝试使用CAS操作来进行更新。若CAS一直不成功,自旋等待将会大大影响CPU性能。
只能保证一个共享变量的原子操作
当我们一次操作涉及多个共享变量时,由于不同变量可能分别被不同线程实现CAS操作,所以是无法保证原子性的
解决方法是可以将多个共享变量通过某种方法组合为一个变量在进行操作,比如假设a,b各为一个共享变量,那么我们可以设置c=a*b为CAS对象,或者将多个变量封装进一个对象里,通过AtomicReference类来实现对象间原子性的保证,间接实现各个共享变量的原子性保证
【免责声明】本文系本网编辑部分转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与管理员联系,我们会予以更改或删除相关文章,以保证您的权益!更多内容请加danei456学习了解。欢迎关注“达内在线”参与分销,赚更多好礼。