【java并发编程艺术学习】(五)第二章 java并发机制的底层实现原理 学习记录(三) 原子操作的实现原理学习
章节介绍
主要包括 术语定义、处理器如何实现原子操作、Java如何实现原子操作;
原子(atomic)本意是 不能再进一步分割的最小粒子,“原子操作” 意为 不可被中断的一个或一系列操作。
术语定义
自己的理解:
缓存行:缓存的最小操作单位。注意,缓存与内存是不一样的。
比较并交换:结合上一篇中CAS操作的介绍进行理解。CAS操作需要输入两个数值,一个新值A,一个旧值B,在操作期间先比较旧值B有没有发生变化,没有发生变化,才交换,发生了变化,就不交换。
CPU流水线:结合生产车间的流水线,一种设备或者工人只做一个工作,等这几个设备或者工人都工作了一遍,也就是完成了一个CPU的时钟周期。
内存顺序冲突:这一般是指多个CPU同时修改同一个缓存行的不同部分而引起其中一个CPU的操作无效,当出现这个内存顺序冲突时,CPU必须清空流水线。
处理器如何实现原子操作
(1)使用总线锁保证原子性
如果多个处理器同时对共享变量进行改写操作(经典例子 i++),那么共享变量就会被多个处理器同时进行操作,这样读改写操作就不是原子的,操作完之后共享变量的值会和期望的不一样。以 i++ 为例,如果我们进行两次i++操作,我们期望的值是3,但是可能是2。原因可能是 多个处理器同时从各自的缓存中读取变量,分别进行了加 1 操作,然后分别写入到系统内存中。
那么,想要保证读改写共享变量时候的操作时原子的,就必须保证在一个处理器读改写共享变量的时候,其他处理器不能操作缓存了该共享变量内存地址的缓存。处理器使用总线索来解决这个问题。总线索 就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出该信号时,其他处理器的请求就处于阻塞,该处理器可以独占共享内存。
(2)使用缓存锁保证原子性
在同一个时刻,我们只需要保证对某个内存地址的操作是原子性即可,但总线锁定把CPU和内存之间的通信锁定了,这样造成的后果就是,在总线锁定期间,其他处理器不能操作其他内存地址的数据,所以总线锁定的开销比较大。
频繁使用的内存会缓存在处理器的L1、L2、L3的高速缓存里,那么原子操作就可以直接在内部缓存中进行,并不需要声明总线锁。
缓存锁定:如果内存区域被缓存到处理器的缓存行中,并且在LOCK操作期间被锁定,那么当它执行锁操作回写到内存时,处理器不在总线上声言LOCK#信号,而是修改内部分存储地址,并允许他的缓存一致性机制来保证操作的原子性,因为缓存一致性机制会阻止同时修改由两个以上处理器缓存的内存区域数据,当其他处理器回写已被锁定的缓存行的数据时,会使缓存行无效。以 多个处理器 执行 i++为例,如果CPU1修改缓存行中的i时使用了缓存锁定,那么CPU2等就不能同时缓存 i 的缓存行。
关键字:为例保证各个处理器的缓存一致、缓存一致性协议、每个处理器、嗅探、总线、数据、检查、过期、无效状态、内存、重新读取
备注:可以结合 volatile的实现原则进行理解学习。
特殊情况,不能使用缓存锁定:(1)当操作的数据不能被缓存在处理器内部,或操作的数据跨多个缓存行,则处理器会调用总线锁定;
(2)有些处理器不支持缓存锁定。
Java如何实现原子操作?
在Java中可以通过 锁 和 循环CAS的方式来实现。
(1)使用循环CAS操作实现原子操作。自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止,举例:实现一个基于CAS线程安全的计数器方法。
从Java1.5开始,JDK的并发包里提供了一些类用于支持原子操作,如 AtomicBoolean(用原子的方式更新boolean值)、Atomicinteger(用原子的方式更新int值)和AtomicLong(用原子方式更新long值)。这些包装类中还提供了有用的工具方法,比如 以原子的方式将当前值自增1 和 自减1。
(2)CAS实现原子操作的问题
ABA问题;循环时间长开销大;只能保证一个共享变量的原子操作。
ABA问题说明:在CAS操作 值的时候,会检查值有没有发生变化。如果一个值原来是A,变成了B,又变成了A,这样的话,用CAS检查时候,会发现他的值没有变化,实际上却发生变化了。解决思路就是 使用版本号。每次变化,都会更新版本号:1A-->2B-->3A。
从Java1.5开始,JDK的Atomic包里提供了一个类 AtomicStampedReference 来解决ABA问题。这个类的 compareAndSet方法的作用是首先检查当前引用是否等于预期引用,并且检查当前标志是否等于预期标志。如果都相等,则把该引用 和该标志的值都更新为给定的值。
自旋CAS如果长时间不能成功,会给CPU带来非常大的执行开销。如果JVm能够支持处理器提供的pause命令,那么效率会有一定的提升。
对一个共享变量执行操作时候,我们可以循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性了,这是就得使用 锁。取巧的方式:多个共享变量合并成一个共享变量来操作。举例:i = 2; j = a ,合并为 ij = 2a。
从Java 1.5开始,JDK提供了AtomicReference类来保证引用对象之间的原子性,就可以把多个变量放在一个对象里来进行CAS操作。(备注:这里需要详细看下是如何处理的.....)
(3)使用锁机制实现原子操作
锁机制保证了只有获取锁的线程才能操作锁定的内存区域。除了偏向锁,JVM实现锁的方式都用了循环CAS,即当一个线程想进入同步块的时候使用循环CAS的方式来获取锁,当它退出同步块的时候使用循环CAS释放锁。(备注:后半部分,我还得好好理解下...)
【java并发编程艺术学习】(五)第二章 java并发机制的底层实现原理 学习记录(三) 原子操作的实现原理学习的更多相关文章
- Android艺术开发探索——第二章:IPC机制(下)
Android艺术开发探索--第二章:IPC机制(下) 我们继续来讲IPC机制,在本篇中你将会学习到 ContentProvider Socket Binder连接池 一.使用ContentProvi ...
- java并发编程实战笔记---(第二章)线程安全:正确性
ThreadA__________ 同步 ______________ 异步 ___________ 异步 ThreadB__________ ____________ ...
- 如何评价《Java 并发编程艺术》这本书?
对于书评这件事情,我其实是不想写的,因为每个人都有自己的一个衡量标准,每个人眼中都有自己的哈姆雷特,是好是坏每个人都褒贬不一.如果对于书中的知识你都掌握了,你只是想把它作为一种知识串联的记忆体的话,那 ...
- [书籍翻译] 《JavaScript并发编程》第五章 使用Web Workers
本文是我翻译<JavaScript Concurrency>书籍的第五章 使用Web Workers,该书主要以Promises.Generator.Web workers等技术来讲解Ja ...
- java并发编程笔记(五)——线程安全策略
java并发编程笔记(五)--线程安全策略 不可变得对象 不可变对象需要满足的条件 对象创建以后其状态就不能修改 对象所有的域都是final类型 对象是正确创建的(在对象创建期间,this引用没有逸出 ...
- Java程序设计(2021春)——第二章课后题(选择题+编程题)答案与详解
Java程序设计(2021春)--第二章课后题(选择题+编程题)答案与详解 目录 Java程序设计(2021春)--第二章课后题(选择题+编程题)答案与详解 第二章选择题 2.1 面向对象方法的特性 ...
- java面向对象编程——第二章 java基础语法
第二章 java基础语法 1. java关键字 abstract boolean break byte case catch char class const continue default do ...
- Android开发艺术探索——第二章:IPC机制(中)
Android开发艺术探索--第二章:IPC机制(中) 好的,我们继续来了解IPC机制,在上篇我们可能就是把理论的知识写完了,然后现在基本上是可以实战了. 一.Android中的IPC方式 本节我们开 ...
- Java Persistence with MyBatis 3(中文版) 第二章 引导MyBatis
MyBatis最关键的组成部分是SqlSessionFactory,我们可以从中获取SqlSession,并执行映射的SQL语句.SqlSessionFactory对象可以通过基于XML的配置信息或者 ...
随机推荐
- platform-tools
platform-tools包含开发app的平台依赖的开发和调试工具,包括 adb.fastboot等 android sdk里的各目录作用 AVD Manager.exe:虚拟机管理工具,用于建立和 ...
- Yii2发送短信验证码完全解决方案
概述 在做项目的时候,需要用到短信发送验证码功能.不能不说Yii2的牛逼,很容易就搞定了.下面我整理一下具体功能和流程,分享给大家. 主要功能 通过Yii2 rules验证手机号 通过js验证是否为手 ...
- window.location.assign和window.location.href区别
window.location.assign和window.location.href区别 window.location.assign(url)和window.location.href=url实现 ...
- 每天一个Linux命令(23)chmod命令
chmod命令用来变更文件或目录的权限. 在UNIX系统家族里,文件或目录权限的控制分别以读取.写入.执行3种一般权限来区分,另有3种特殊权限可供运用.用户可以使用chmod指令去变更文件与目 ...
- inline-block元素的4px空白间距解决方案
http://www.jb51.net/css/68785.html inline-block元素的4px空白间距解决方案
- sqlserver 2008 创建数据库的时候不是空库,里面总有数据的解决办法
SqlServer2008 里面有个系统数据库 Model 数据库,在创建新数据库的时候,会以它为模板创建,所以如果发现你的Model数据库比较大,说明里面有很多模板数据.此时如果需要去创建没有数据的 ...
- 关于 haproxy keepalived的测试
可以阅读的一篇文章(http://blog.csdn.net/xyang81/article/details/52554398) 以下测试的配置都是基本的,简单化的,达到了效果滴,没有参考上面文档 准 ...
- 访问虚拟机中的架设的Web服务器
环境: 1.虚拟机中安装了CentOS,虚拟机使用NAT的方式 2.在CentOS中安装了APACHE 并且使用 http://127.0.0.1可以正常访问,通过ifconfig查到IP地址是 19 ...
- Spark- Spark基本工作原理
Spark特点: 1.分布式 spark读取数据时是把数据分布式存储到各个节点内存中 2.主要基于内存(少数情况基于磁盘,如shuffle阶段) 所有计算操作,都是针对多个节点上内存的数据,进行并行操 ...
- java:Maven构建项目速度太慢的解决办法,以及报错Retrieving archetypes:' has encountered a problem
如果报错信息如下: Retrieving archetypes:' has encountered a problemAn internal error occurred during:"R ...