JAVA多线程之先行发生原则

一、引子  

  如果java内存模型中所有的有序性都仅仅依靠volatile和synchronized来完成,那么有一些操作会变得很繁琐,但我们在编写java并发代码时并未感觉到这一点,这是因为java语言中有个先行发生原则(happens-before),通过这个原则,我们可以通过几条规则一揽子解决并发环境下两个操作之间是否可能存在冲突的所有问题。

二、定义

  先行发生是java内存模型中定义的两项做错之间的偏序关系,如果说操作A先行发生与操作B,其实就是说在发生操作B之前,操作A产生的影响能被操作B观察到,“影响”包括修改了内存中共享变量的值、发送了消息、调用了方法等。

三、规则
  java内存模型中“天然的”的先行发生关系规则如下:
  1、程序次序规则:
    在一个线程内,按照程序代码顺序,,书写在前面的操作先行发生于书写在后面的操作,准确的说,应该是控制流程序而不是程序代码顺序,因为要考虑分支、循环等结构;
  2、管程锁规则:
    一个unlock操作先行发生于后面对同一个锁的lock操作,这里必须强调的是同一个锁,“后面”指的是时间上的先后顺序。
  3、volatile变量规则:
    对一个volatile变量的写操作先行发生于后面对这个变量的读操作,“后面”同样是时间上的先后顺序。
  4、线程启动规则:
    Thread对象的start()方法先行发生于次线程的每一个动作;
  5、线程终止规则:
    线程中的所有操作都先行发生于对此线程的终止检测,可以通过Thread.join()方法结束,Thread.isAlive()的返回值等手段检测到线程已终止执行
  6、线程中断规则:
    对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interruptd()方法检测到是否有中断发生
  7、对象终结规则:
    一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的开始
  8、传递性
    如果操作A先行发生于操作B,操作B先行发生于操作C,那么就可以认为操作A先行发生于操作C。

四、示例  

如下案例:

public class TestValue {
    private int value = 0;

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

  如果线程A调用了“setValue(1)”,线程B调用了同一个对象的“getValue()”方法,那么返回值是什么?
    答案是不确定,因为这里的操作不是线程安全的,它不满足上述所有的 先行发生 规则。
  修复方法有好多种,这里列举较为简单的两种:
  1)把getter/setter方法都定义为synchronized方法
  2)把value定义为volatile变量。

时间: 2024-10-13 11:50:11

JAVA多线程之先行发生原则的相关文章

java内存模型—先行发生原则

Java语言中有一个“先行发生”(happens-before)的原则.这个原则非常重要,它是判断数据是否存在竞争,线程是否安全的主要依据,依赖这个原则,我们可以通过几条规则一揽子解决并发环境下两个操作之间是否可能存在冲突的所有问题.现在就来看看“先行发生”原则指的是什么.先行发生是Java内存模型中定义的两项操作之间的偏序关系,如果说操作A先行发生于操作B,其实就是说在发生操作B之前,操作A产生的影响能被操作B观察到,“影响”包括修改了内存中共享变量的值.发送了消息.调用了方法等.这句话不难理

java内存模型先行发生原则

java语言天生有一个  先行发生原则,无须借助任何同步器就存在  这是判断线程是否存在竞争,线程是否安全的主要依据, 1.程序次序规则:在一个线程内,书写在前面的代码先行发生于后面的.确切地说应该是,按照程序的控制流顺序,因为存在一些分支结构. 2.管程锁定规则.一个unlock操作先行发生于后面对同一个锁的lock操作. 3.Volatile变量规则:对一个volatile修饰的变量,对他的写操作先行发生于读操作. 4.线程启动规则:Thread对象的start()方法先行发生于此线程的每一

安全并发之先行发生原则

先行发生原则,可以帮你判定是否并发安全的,从而不必去猜测是否是线程安全了! 如果Java内存模型中所有有序性都靠volatile和synchronized来完成,那么编写代码会很繁琐,但日常Java开发中并没有感受到这一点,正是因为Java语言的"先行发生"原则.这个原则非常重要,它是判断数据是否存在竞争.线程是否安全的主要依据. 先行发生是Java内存模型中定义的两项操作数之间的偏序关系,如果说操作A先行发生于操作B,就是说在发生操作B之前,操作A产生的影响能被操作B观察到,&quo

先行发生原则

如果Java内存模型中所有的有序性都仅仅靠volatile和synchronized来完成,那么有一些操作将会变得很烦琐,但是我们在编写Java并发代码的时候并没有感觉到这一点,这是因为 Java语言中有一个"先行发生"(happens-before)的原则.这个原则非常重要,它是判断数据 是否存在竞争.线程是否安全的主要依据,依靠这个原则,我们可以通过几条规则一揽子地 解决并发环境下两个操作之间是否可能存在冲突的所有问题. 现在就来看看"先行发生"原则指的是什么.

3、先行发生原则

如果Java内存模型中所有的有序性都仅仅依靠volatile和synchronized来完成,那么一些操作将会变得很繁琐,但是我们在编写Java程序时并没有感觉到这一点,这是因为Java语言中有一个”先行发生(happens-before)“的原则.这个原则非常重要,它是判断数据是否存在竞争.线程是否安全的主要依据. 下面是Java内存模型下一些“天然的”先行发生关系,这些先行发生关系无需任何同步协助就已经存在,可以在编码中直接使用.如果两个操作之间的关系不在此例,并且无法从下列规则推导出来的话

40个Java多线程问题总结

前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题. 这些多线程的问题,有些来源于各大网站.有些来源于自己的思考.可能有些问题网上有.可能有些问题对应的答案也有.也可能有些各位网友也都看过,但是本文写作的重心就是所有的问题都会按照自己的理解回答一遍,不会去看网上的答案,因此可能有些问题讲的不对,能指正的希望大家不

JAVA多线程与并发学习总结

1.      计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓存一致性:多处理器系统中,因为共享同一主内存,当多个处理器的运算任务都设计到同一块内存区域时,将可能导致各自的缓存数据不一致的情况,则同步回主内存时需要遵循一些协议. 乱序执行优化:为了使得处理器内部的运算单位能尽量被充分利用. 2.      JAVA内存模型 目标是定义程序中各个变量的访问规则.

Java多线程与并发---学习总结(很详细)

Java多线程与并发---学习总结(很详细) 1.      计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓存一致性:多处理器系统中,因为共享同一主内存,当多个处理器的运算任务都设计到同一块内存区域时,将可能导致各自的缓存数据不一致的情况,则同步回主内存时需要遵循一些协议. 乱序执行优化:为了使得处理器内部的运算单位能尽量被充分利用. 2.      JAVA

Java多线程问题总结

前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题. 这些多线程的问题,有些来源于各大网站.有些来源于自己的思考.可能有些问题网上有.可能有些问题对应的答案也有.也可能有些各位网友也都看过,但是本文写作的重心就是所有的问题都会按照自己的理解回答一遍,不会去看网上的答案,因此可能有些问题讲的不对,能指正的希望大家不