【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的配置信息或者 ...
随机推荐
- Struts2之ModelDriven的使用
http://www.cnblogs.com/luoyanli/archive/2012/11/20/2778361.html 我们可以根据Action属性的不同将它分为两类:Field-Driven ...
- 关于ionic开发中遇到的坑与总结
这次是第二次使用ionic开发混合app,今天算是对这个框架做一个总结,基础的我就不再重复了,网上都有教程.我就说说自己的心得和遇见的各种坑, 之后会陆续补充,想到什么说什么吧. 1.关于ionic效 ...
- SQL优化小结
一 背景 客户数据库经常出现死锁.超时.查询慢等问题,数据库mssql,数据量主要表大概上千W. 二 收集信息 首先是要找出IO大.查询慢.使用频率高的脚本.直接用Profiler ...
- tornado源码分析
初识tornado 首先从经典的helloword案例入手 import tornado.ioloop import tornado.web class MainHandler(tornado.web ...
- 一、Perfect Squares 完全平方数
一原题 Given a positive integer n, find the least number of perfect square numbers (, , , , ...) which ...
- 某国际知名IT公司笔试
原文地址:http://blog.csdn.net/lazy_tiger/article/details/1790986 这段时间没怎么顾及自己的这个“一寸土地”, 实在惭愧.因为这些天小弟又经历了“ ...
- POJ Layout
A - Layout Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit S ...
- pathinfo()的用法
pathinfo() 返回一个关联数组包含有 path 的信息. 包括以下的数组元素: [dirname] [basename] [extension] 提示和注释 注释:如果不是要求取得所有单元,则 ...
- ruanjiangongcheng1
软体工程的方法有很多方面的意义.包括专案管理,分析,设计,程序的编写,测试和质量控制. 软体设计方法可以区别为重量级的方法和轻量级的方法.重量级的方法中产生大量的正式文档. 著名的重量级开发方法包括I ...
- Oracle学习笔记_01_SQL初步
1.分类 SQL语句分为以下三种类型: DML: Data Manipulation Language 数据操纵语言 DDL: Data Definition Languag ...