首页 未命名正文

linux编程_Java可见性机制的原理

云返利网 未命名 2020-05-26 09:05:47 17 0

基本概念

  • 可见性

当一个线程修改了共享变量时,另一个线程可以读取到这个修改后的值。

  • 内存屏障(Memory Barriers)

处理器的一组指令,用于实现对内存操作的顺序限制。

  • 缓冲行

CPU告诉缓存中可以分配的最小存储单元,处理器填写缓存行时,会加载整个缓存行。

  • Lock前缀的指令

Lock前缀的指令在多核处理器下会发生两件事情:

1)将当前处理器的缓存行的数据协会到系统内存。

2)这个写回内存的操作会使其他CPU缓存了该内存的地址的数据无效。

  • 缓存一致性协议

在多处理器下,为零保证各个处理器的缓存是一致的,每个处理器都市通过嗅探在总线上流传的数据来检查自己缓存的值是不是过时了。当处理器发现自己缓存行对应的地址被修改,就会将当前处理器的缓存行设置为无效状态。当处理器对这个数据举行读写的时刻,会重新把数据从内存中读取到处理器缓存中。

  • CAS

CompareAndSwap 对照并交流
CAS操作需要输入两个值,一个旧值(执行CAS操作前的值,期望值)和一个新值,只有当当前值即是旧值时,才可以将当前值设置为新值,否则不设置。这是一个原子操作,由硬件保证。

  • 重排序规则

从根本上来所,JMM 对编译器和处理器的重排序限制只有一条,只要不改变程序执行的效果(指的是单线程或者准确同步的多线程环境下),那么编译器和处理器怎么优化都可以。

Volatile

从上面的Lock前缀指令和缓存一致性协议可以看出来,这就是volatile的实现原理了。
实际上,valatile变量被写入时,确实加了一个Lock前缀的指定,以此来到达可见性的目的。

final

Final域只能被显示地赋值一次,然则这并不代表final域不能被多次初始化。
好比:final int i ;i在组织函数中被赋值之前,就会被初始化为默认的值:0.通过调试代码可以证实这一点。

为了保证final域的值不会在为初始化的情况下被访问到,程序员只需要保证一点即可:即,在组织函数中,正在被组织的工具(this)没有“逸出”,那么不需要任何同步手段,就能保证随便线程看到的final域,包罗基本类型和引用类型,都是已经被准确地通过组织函数初始化过了的。

一个会是正在被组织的工具逸出的例子:

public class FinalTest{
   final int i;
   static FinalTest obj;

   public FinalTest(){
   i  =1;
   /** *这里会使正在被组织的工具逸出,若是和上一句做了重排序,那么其他线程就可以通过obj访问到还为被初始化的final域。 **/
   obj = this; 
  }
}

Happens-Before规则

happens-before的寄义

Happen-Before规则用来形貌两个操作之间的顺序关系,这两个操作可以再一个线程内,也可以不再一个线程内。此顺序并不严酷意味着执行时间上的顺序,而是至前一个操作的效果要对后一个操作可见。

Happens-Before关系的界说如下:

  • 若是一个happens-before另一个操作,那么第一个操作的执行效果对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前
  • 两个操作之间存在happens-before关系,并不意味着Java平台的详细实现必须根据happens-before关系指定的顺序来执行。若是重排序之后的执行效果,与根据happens-before关系来执行的效果一致,那么这种重排序并不非法。

举例来说,若是在程序执行顺序上,A先于B,而且A修改了共享变量,而B正好使用该共享变量,那么A需要happen-before B,再直白一点,就是A对共享变量的修改,需要在B执行时,对B可见。

happens-before规则

  1. 程序顺序规则:一个线程中的每个操作,happens-before于该线程中的随便后续操作。
  2. 监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
  3. volatile规则:对一个volatile域的写,happens-before于随便后续对这个volatile域的读。
  4. 传递性:若是Ahappens-before B,而且B happens-before C,那么A happens-before C。
  5. start()规则:若是线程A执行操作ThreadB.start(),那么A线程的ThreadB.start()操作happens-before于线程B中的随便操作。
  6. join()规则:若是线程A执行操作ThreadB.join()并乐成返回,那么线程B的随便操作happens-before于线程A从ThreadB.join()操作乐成返回。

【关于云返利网】

云返利网是阿里云、腾讯云、华为云产品推广返利平台,在各个品牌云产品官网优惠活动之外,云返利网还提供返利。您可以无门槛获得阿里云、华为云、腾讯云所有产品返利,在官网下单后就可以领取,无论是自己用、公司用还是帮客户采购,您个人都可以获得返利。云返利网的目标是让返利更多、更快、更简单!详情咨询13121395187(微信同号)