• Java中锁的内存语义


      我们都知道,Java中的锁可以让临界区互斥执行。锁是Java并发编程中最重要的同步机制,锁除了可以让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息。下面是锁的释放-获取的代码:

      

    Class MonitorEx{
        int a = 0 ;
        public synchronized void writer(){  //1
            a++ ;                           //2
    
        }                      //3
        
        public synchronized void reader(){  //4
    
            int i = a ;                     //5
            ......  
        }                                   //6
    
    
    }
    

      假设线程A执行writer()方法,随后线程B执行reader()方法。根据happens-before规则,这个过程包含的happens-before关系有如下3类 :

      (1)根据程序次序规则 : 1 happens-before 2 , 2 happens-before 3 , 4 happens-before 5 , 5 happens-before 6 ;

      (2)根据监视器规则 : 3 happens-before 4 ;

      (3)根据传递依赖规则 : 2 happens-before 5 ;

      happens-before 关系可以转换为如下图的表现形式 :

      

       在上图中,每一个箭头连接的两个点,代表了一个happens-before 关系,短箭头表示的是程序的顺序规则 ; 红色箭头表示监视器规则;黑色长箭头表示的是组合这些规则后提供的happens-before保证 。  

      上图表示线程A在释放了锁之后,随后线程B获取同一个锁,2 happens-before 5 。因此,线程A在释放锁之前所有的可见的共享变量,在B线程获取同一个锁之后,将立刻变得对线程B可见。

      

      以上的介绍是对我们程序员可见的,那么锁的释放和获取在内存中的语义是怎么样的呢 ?

      当线程释放锁时,Java内存模型(Java Memory Modle 简称JMM) 会把该线程对应的本地内存中的共享变量刷新到主内存中,以上面的例子为例,当线程A释放锁后,共享数据的状态示意图如下图所示 :

      当线程获取锁时,JMM会把该线程对应的本地内存置为无效,从而使得被监视器保护的临界区代码必须从主内存中读取共享变量。下图表示锁获取的状态示意图 :

      锁的释放和锁的获取的内存语义可以总结如下:

      □ 线程A释放一个锁,实质上是线程A向接下来要获取同一个锁的某个线程发出了(线程A对共享变量做出修改)消息 。

      □ 线程B获取一个锁,实质上是线程B接收了之前某个线程发出的(在释放这个锁之前对共享变量所做修改)的消息。

      □ 线程A释放锁,随后线程B获取这个锁,这个过程实质上是线程A通过主内存向线程B发送消息 。

      

      

         

      

      

      

  • 相关阅读:
    JS中数组的sort()排序
    清除浮动方法
    浏览器兼容问题
    前端切图
    设置页面默认为繁体字
    7月计划
    css的层叠和继承
    Flex 布局教程:语法篇
    轮播图淡入淡出的js和jquery的效果
    接口调用async/await
  • 原文地址:https://www.cnblogs.com/dquery/p/7002348.html
Copyright © 2020-2023  润新知