java并发编程学习(三) 原子操作的实现原理及java中如何实现原子操作

              原子操作,就是一个或者一系列不能中断的操作,并发编程中经常遇见的原子性问题。了解之前,先介绍下一些术语。

cpu术语定义
术语名称 解释
缓存行 缓存的最小操作单位
比较并交换  cas cas 比较并交换,一个新值
cpu流水线
cpu中由5~6个电路单元组成一个指令处理流水线,然后将一条x86指令分为5~6布交由执行,这样在一个cpu的时钟周期内完成一个指令
内存顺序冲突
内存顺序冲突一般是由假共享引起的。假贡献指的是多个cpu修改一个缓存行的不同部分,导致其中一个cpu的操作无效,出现这个问题必须清空流水线


     处理器如何实现原子操作

1>  使用总线锁保证原子性。举个例子,多个cpu从各自的缓存中读取i,并将其加1后,各自写入到系统内存中,那么想要保证读改写变量的操作是原子性,就必须保证cpu1读改写i时候,CPU2不能操作缓存了该变量内存地址的缓存。

     处理器使用总线锁就是解决这个问题的,总线锁指的是使用处理器提供的一个#lock信号,当一个处理器在总线上输出此信号时候,其他处理器的请求将被阻塞,那么该处理器就会独占共享内存

2>  通过缓存锁保证原子性。

     在同一时刻,只要保证CPU对某个内存地址的操作是原子性的就行,但是总线锁定把CPU和内存的通信锁定了, 使得锁定期间其他处理器不能操作其他内存地址的数据,开销大。

    java如何实现原子操作

java中通过锁和循环cas的方式来实现原子操作。

1. 使用循环cas的方式实现原子操作,使用atomicXX  的类实现自增1,自减1 的原子操作

     循环cas的问题

   虽然解决了原子操作,但是ABA问题,循环开销时间长,以及只能保证一个共享变量的原子操作。

   1> ABA 问题 :

    cas 检查在操作值的时候,检查值有没有发生变化,但是如果一个值是A,变为B,有改为A,这样cas无法检查  出来,解决方案使用atomic包中的AtomicStampedReference类的compareandset解决,这个类的方法会检查引用和标志位。如果都相等,才去更新值

   2> 循环开销时间长

   3> 只能保证一个变量的原子操作。如果有两个共享变量 i=2,j=a 合并为ij=2a操作。

2. 使用锁机制来保证原子操作,锁机制保证只有获取锁的线程才能操作锁定的内存区域。



*  学习笔记来自 阿里专家 方腾飞 《并发编程的艺术》

你可能感兴趣的:(多线程,多线程学习)