• 14. happens-before模型


    1 happens-before产生背景

    我们前面说过由于存在线程本地内存和主内存的原因,再加上重排序,会导致多线程环境下存在可见性的问题。那么我们正确使用同步、锁的情况下,线程A修改了变量a何时对线程B可见?

    我们无法就所有场景来规定某个线程修改的变量何时对其他线程可见,但是我们可以指定某些规则,这规则就是happens-before,从JDK 5 开始,JMM就使用happens-before的概念来阐述多线程之间的内存可见性。也就说这仅仅是一种规则描述,而不是技术实现。

    因此happens-before不仅仅局限于volatile,而是针对整个Java的,从JDK 5开始,Java使用新的JSR-133内存模型。JSR-133使用happens-before的概念来阐述操作之间的内存可见性。在JMM中,如果一 个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关 系。这里提到的两个操作既可以是在一个线程之内,也可以是在不同线程之间。

    2 happens-before规则介绍

    (1)程序顺序规则 1.不能改变程序的执行结果(在单线程环境下,执行的结果不变.) 2.依赖问题, 如果两个指令存在依赖关系,是不允许重排序 例如,这里的c=a*b一定要求前两个赋值完成才可以执行,但是这里并没要求b=1要早与a=1。

    1. void test(){
    2. int a=1; a
    3. int b=1; b
    4. int c=a*b; c
    5. }

    描述就是“b happens before c”。 需要注意的是,这个的含义是c执行的时候b的结果已经是可见的了,而不是规定指令执行的顺序。

    (2)传递性规则 如果A happens-before B,且B happens-before C,那么A happens-before C (3)volatile变量规则 对一个volatile域的写,happens-before于任意后续对这个volatile域的读。

    再看个例子:

    1. 定义了一个变量
    2. volatile int a=0
    3. a=10*2;
    4. System.out.print(a);
    5. public class VolatileExample {
    6. int a=0;
    7. volatile boolean flag=false;
    8. public void writer(){
    9. a=1; 1
    10. flag=true; //修改 2
    11. }
    12. public void reader(){
    13. if(flag){ //true 3
    14. int i=a; //1 4
    15. }
    16. }
    17. }

    1 happens-before 2 是否成立? 是,为什么?这个是volatile导致的一条规则,记住就行了 。

    3 happens-before 4 是否成立 是

    然后有 2 happens -before 3 ->volatile规则

    所以最终 1 happens-before 4 ; i=1成立

    (4)监视器锁规则 对一个锁的解锁,happens-before于随后对这个锁的加锁。例如下面对x进行两次加锁,则前一个解锁一定早于下一个加锁操作。

    1. int x=10;
    2. synchronized(this){
    3. //后续线程读取到的x的值一定12
    4. if(x<12){
    5. x=12;
    6. }
    7. }

    start规则 这里其实也是为子线程的初始化提供条件。

    1. int x = 0;
    2. Thread t1 = new Thread(() -> {
    3. //读取x的值 一定是20
    4. if (x == 20) {
    5. }
    6. });
    7. x = 20;
    8. t1.start();
    9. }

    Join规则

    1. public class Test{
    2. int x=0;
    3. Thread t1=new Thread(()->{
    4. x=200;
    5. });
    6. t1.start();
    7. t1.join(); //保证结果的可见性。
    8. //在此处读取到的x的值一定是200.
    9. }

  • 相关阅读:
    探索LLM在图上学习的潜力10.14 暂停
    计算机毕业设计之java+SSM酒店客房预定管理系统
    Leetcode 850. 矩形面积 II
    动态TopicModel BERTopic 中文 长文本 SentenceTransformer BERT 均值特征向量 整体特征分词关键词
    更强大的 MQTT over QUIC 桥接 & Azure 桥接
    腾讯云轻量数据库性能如何?轻量数据库租用配置价格表
    Byzantine Generals Problem
    Android tinker升级之路分析
    js--处理object的常用方法
    url找不到404的问题,url被拼接
  • 原文地址:https://blog.csdn.net/xueyushenzhou/article/details/126653637