zoukankan      html  css  js  c++  java
  • 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发送消息 。

      

      

         

      

      

      

  • 相关阅读:
    Win32汇编
    Boost ASIO 实现异步IO远控
    Python 使用oslo.vmware管理ESXI虚拟机
    Python 巡检接入钉钉机器人
    Django Ajax序列化与反序列化
    Nacos 认证绕过
    Lanproxy 遍历目录漏洞 CVE-2021-3019 附批量POC
    Apache Solr 全版本任意读取文件漏洞
    垂直水平居中的多种方法 主要的4种
    vue provide/inject 父组件如何给孙子组件传值
  • 原文地址:https://www.cnblogs.com/dquery/p/7002348.html
Copyright © 2011-2022 走看看