Java一致性的实现

一致性

 

 

内存模型

每一个线程有一个工作内存和主存独立

工作内存存放主存中变量的值的拷贝

 

 

Happen Before

  • 1、程序次序规则:在一个单独的线程中,按照程序代码的执行流顺序,(时间上)先执行的操作happen—before(时间上)后执行的操作。
  • 2、管理锁定规则:一个unlock操作happen—before后面(时间上的先后顺序,下同)对同一个锁的lock操作。
  • 3、volatile变量规则:对一个volatile变量的写操作happen—before后面对该变量的读操作。
  • 4、线程启动规则:Thread对象的start()方法happen—before此线程的每一个动作。
  • 5、线程终止规则:线程的所有操作都happen—before对此线程的终止检测,可以通过Thread.join()方法结束、Thread.isAlive()的返回值等手段检测到线程已经终止执行。
  • 6、线程中断规则:对线程interrupt()方法的调用happen—before发生于被中断线程的代码检测到中断时事件的发生。
  • 7、对象终结规则:一个对象的初始化完成(构造函数执行结束)happen—before它的finalize()方法的开始。
  • 8、传递性:如果操作A happen—before操作B,操作B happen—before操作C,那么可以得出A happen—before操作C。

 

 

当数据从主内存复制到工作存储时,必须出现两个动作:第一,由主内存执行的读(read)操作;第二,由工作内存执行的相应的load操作;当数据从工作内存拷贝到主内存时,也出现两个操作:第一个,由工作内存执行的存储(store)操作;第二,由主内存执行的相应的写(write)操作

每一个操作都是原子的,即执行期间不会被中断

对于普通变量,一个线程中更新的值,不能马上反应在其他变量中

如果需要在其他线程中立即可见,需要使用 volatile 关键字

CAS(Compare And Swap)

非阻塞同步指令之一,硬件指令集支持。先进行操作,如果有并发操作,则不断重试直到成功。

 

 

final不可变

作用于类、方法、成员变量、局部变量。初始化完成后的不可变对象,其它线程可见。常量不会改变不会因为其它线程产生影响。Final修饰的引用类型的地址不变,同时需要保证引用类型各个成员和操作的线程安全问题。因为引用类型成员可能是可变的。

 

synchronized同步

作用域代码块、方法上。通过线程互斥,同一时间的同样操作只允许一个线程操作。通过字节码指令实现。

Volatile

  1. volatile 修饰的变量的变化保证对其它线程立即可见。

    volatile变量的写,先发生于读。每次使用volatile修饰的变量个线程都会刷新保证变量一致性。但同步之前各线程可能仍有操作。如:各个根据volatile变量初始值分别进行一些列操作,然后再同步写赋值。每个线程的操作有先后,当一个最早的线程给线程赋值时,其它线程同步。但这时其它线程可能根据初始值做了改变,同步的结果导致其它线程工作结果丢失。

    根据volatile的语意使用条件:运算结果不依赖变量的当前值。

  2. volatile禁止指令重排优化。

    这个语意导致写操作会慢一些。因为读操作跟这个没关系。

     

    并发包概述

    java.util.concurrent 包含许多线程安全、测试良好、高性能的并发构建块。不客气地说,创建java.util.concurrent 的目的就是要实现 Collection 框架对数据结构所执行的并发操作。通过提供一组可靠的、高性能并发构建块,开发人员可以提高并发类的线程安全、可伸缩性、性能、可读性和可靠性。

    此包包含locks,concurrent,atomic 三个包。

    Atomic:原子数据的构建。

    Locks:基本的锁的实现,最重要的AQS框架和lockSupport

    Concurrent:构建的一些高级的工具,如线程池,并发队列等。

    其中都用到了CAScompare-and-swap)操作。CAS 是一种低级别的、细粒度的技术,它允许多个线程更新一个内存位置,同时能够检测其他线程的冲突并进行恢复。它是许多高性能并发算法的基础。在 JDK 5.0 之前,Java 语言中用于协调线程之间的访问的惟一原语是同步,同步是更重量级和粗粒度的。公开 CAS 可以开发高度可伸缩的并发 Java 类。这些更改主要由 JDK 库类使用,而不是由开发人员使用。

    CAS操作都封装在java 不公开的类库中,sun.misc.Unsafe。此类包含了对原子操作的封装,具体用本地代码实现。本地的C代码直接利用到了硬件上的原子操作。

     

     

posted @ 2017-07-08 13:51 jiumao 阅读(...) 评论(...) 编辑 收藏