Java@深入理解Java虚拟机:高效并发之Java内存模型( 二 )


  • 不允许一个线程丢弃它最近的assign操作 , 即变量在工作内存中改变了之后必须把该变化同步回主内存 。
  • 不允许一个线程没有发生过任何assigin操作把数据从线程的工作内存同步回主内存中 。
  • 一个新的变量只能在主内存中\"诞生\" , 不允许在工作内存中直接使用一个未被初始化(load或assign)的变量 , 就是对一个变量实施use、store操作之前 , 必须先执行assigin和load操作 。
  • 一个变量在同一时刻只允许一条线程对其进行lock操作 , 但lock操作可以被同一线程重复执行多次 , 多次执行lock后 , 只有执行相同次数的unlock操作 , 变量才会被解锁 。
  • 如果对一个变量事先没有被lock操作锁定 , 那就不允许对它执行unlock操作 , 也不允许去unlock一个被其他线程锁定的变量 。
  • 对一个变量unlock操作之前 , 必须先把此变量同步回主内存中(执行store、write操作) 。
  • volatile特性
    1. 保证此变量对所有线程的可见性 , 但对于运算不是原子操作(当一条线程修改了一个变量的值 , 新值对于其他线程来说是可以立即得知的) 。

    • 由于volatile变量只能保证可见性 , 在不符合规则的运算场景中 , 仍然需要枷锁来保证原子性
      • 运算结果不依赖变量的当前值 , 或者能够保证只有单一的线程修改变量的值 。
      • 变量不需要与其他的状态变量共同参与不变约束 。
    1. 禁止指令重排序优化 。

    原子性、可见性与有序性
    1. 原子性:基本数据类型的访问、读写都是具备原子性的;大范围的原子性保证(synchronized)
    2. 可见性:当一个线程修改了共享变量的值时 , 其他线程能够立即得知这个修改 。 (synchronized、final)
    3. 有序性:volatile、synchronized两个关键字保证线程之间的有序性;volatile禁止了指令重排序 , synchronized则是一个变量在同一个时刻只允许一条线程对其进行了lock操作 。
    Happens-before原则
    1. 程序次序规则:在一个线程内 , 按照控制流顺序 , 书写在前面的操作先行发生于书写在后面的操作 。
    2. 管程锁定规则:一个unlock操作先行生发于后面对同一个锁的lock操作 。
    3. volatile变量规则:对一个volatile变量的写操作先行发生于后面对这个变量的读操作 。
    4. 线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作 。
    5. 线程终止规则:线程中的所有操作都先行发生于对此线程的终止检查 , 通过Thread::join()方法是否结束、Thread::isAlive()的返回值等检测线程是否已经终止执行 。
    6. 对象终结规则:一个对象的初始化完成先行发生于它的finalize()方法的开发 。