狐言不胡言

导航

线程安全之可见性(二)

一:不可见的原因

上一部分,根据代码可以知道,产生不可见的原因有两点:

1:CPU高速缓存会造成极短时间内数据的不可见

2:指令重排是导致不可见的主要原因

二:Java内存模型(JMM)

       java内存模型主要是描述多线程程序的语义,多个线程对数据进行了修改,该读取哪个的问题;Java内存模型并没有规定如何去实现多线程程序,只是制定了一些合法行为,即规则;Java内存模型对内存分为工作内存和主内存,也就是栈内存和堆内存。

三:线程间的操作

       java内存模型只规定线程间的操作,有以下几种:read,write,volidate read,volidate write,线程start和start的线程的第一步操作,线程结束。

     冲突和数据竞争:冲突就是线程间,有一个读操作和一个写操作,造成了冲突

四:JMM规则

    1:同步规则

      1.1 volidate的写操作,对后续volidate的读操作同步。

  也就是说用volidate修饰的变量,写入后,对其他线程是可见的。

  1.2 unlock之后的操作,对后续的lock同步。

   加锁和解锁不能重排序,也不能缓存,和volidate一样,t1线程释放锁之后,对后续的加锁是可见的。

  1.3 t1线程的start操作,对t1的第一步操作同步。

      也就是说,再主线程内启动t1,对t1线程内部的操作是可见的。其实就是t1线程再启动之前是NEW状态,主线程把t1线程实例化后,主内存中保存了t1的状态信息,start之后,t1线程的状态变为RUNNABLE,这个状态对t1是可见的,不能够缓存。

  1.4 t1线程最后一步的操作,对后续的线程是可见的。

        和1.3一样,也是在主内存中的状态信息是可见的,不能被缓存。

  1.5 t1线程的interrupt操作,对其他线程是同步的。

       interrupt操作后,对其他线程是可见的。

  2:happens-before(先行发生原则)

  2.1 volidate的写操作,happens-before其他线程的读操作,即写操作发生在读操作之前。

  2.2 线程的unlock操作,happens-before其他线程的lock操作。

  2.3 线程的start操作,happens-before此线程的所有操作。

  2.4 若在t1线程中使用了t2.join,那么t2的操作对t1是可见的。

  2.5 若A happens-before B,B happens-before C,那么A happens-before C。

posted on 2021-04-16 14:59  狐言不胡言  阅读(60)  评论(0编辑  收藏  举报