• JVM-- 先行发生原则


    本文中需要的基础知识:指令重排

    线程中两个非常重要的问题就是:原子性与可见性.

    而下面的先行发生原则就是用来解决可见性问题的.

    先行发生原则--是判断是否存在数据竞争、线程是否安全的主要依据。

    先行发生是Java内存模型中定义的两项操作之间的偏序关系。如果说操作A先行发生于操作B,其实就是说在发生操作B之前,操作A产生的影响被操作B察觉。

    以下面的一段伪代码为例:

    //以下操作在线程A中执行
    int i = 1;
    
    //以下操作在线程B中执行
    j = i;
    
    //以下操作在线程C中执行
    i = 2

    由于线程执行的先后顺序不同,会导致最后j 的结果出现差异。若使线程安全,那么A先行发生B,B先行发生C。

    线程B可能获取的是一些过期的数据。故线程不安全!

    但是在Java内存模型中确实存在一些已经存在的先行发生关系,这些先行发生关系不需要任何的同步操作,就可以保证其线程安全!

    1、程序次序规则在一个线程内,书写在前面的代码先行发生于后面的。确切地说应该是,按照程序的控制流顺序,因为存在一些分支结构。

    2、Volatile变量规则对一个volatile修饰的变量,对他的写操作先行发生于读操作。

    3、线程启动规则。Thread对象的start()方法先行发生于此线程的每一个动作。

    4、线程终止规则。线程的所有操作都先行发生于对此线程的终止检测。

    5、线程中断规则。对线程interrupt()方法的调用先行发生于被中断线程的代码所检测到的中断事件。

    6、对象终止规则。一个对象的初始化完成(构造函数之行结束)先行发生于发的finilize()方法的开始。

    7、传递性A先行发生B,B先行发生C,那么,A先行发生C。

    8、管程锁定规则。一个unlock操作先行发生于后面对同一个锁的lock操作。

    以上就是Java无需任何的同步手段就能成立的先行发生规则。其他情况下就没有顺序保障,虚拟机可以对它们随意地进行重排序。

    总结:

      happens-before指的是前面发生的操作的结构对于后面的操作的结果都是可见的,而在真正操作中并不一定前面的操作就先进行.

    执行E的时候,E是不是保证看见C呢? 
    由法则1,hb(D,E) 
    由法则8,hb(B,D) 
    由法则1, hb(A,B) 
    综上可以推出,hb(A, E),但是推不出hb(C, E) 
    所以,E不一定能看见C,但是E一定能看见A,所以执行E的时候,有可能thread2看到的x的值还是1

      

  • 相关阅读:
    showSoftInput不起作用
    GridView在PopWindow中OnItemClick不响应
    白盒测试范围
    Winform的ListBox的ValueMember和DisplayMember绑定的名称所属对象必须是Public的。
    谷歌浏览器安装adblock广告屏蔽插件
    php+curl上传文件
    win10我能ping通他人,但他人ping不同我
    自己的配置文件以及操作
    安装redis,执行make test时遇到You need tcl 8.5 or newer in order to run the Redis test
    安装redis时遇到zmalloc.h:50:31: 致命错误:jemalloc/jemalloc.h:没有那个文件或目录
  • 原文地址:https://www.cnblogs.com/plxx/p/4376205.html
Copyright © 2020-2023  润新知