深入Java内存模型之阅读理解(2)「建议收藏」

深入Java内存模型之阅读理解(2)

大家好,又见面了,我是全栈君。

锁的释放-获取建立的happens before 关系

锁是java并发编程中最重要的同步机制。锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息。

下面是锁释放-获取的示例代码:

class MonitorExample {
    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 关系可以分为两类:

  1. 根据程序次序规则,1 happens before 2, 2 happens before 3; 4 happens before 5, 5 happens before 6。
  2. 根据监视器锁规则,3 happens before 4。
  3. 根据happens before 的传递性,2 happens before 5。

上述happens before 关系的图形化表现形式如下:

深入Java内存模型之阅读理解(2)「建议收藏」

在上图中,每一个箭头链接的两个节点,代表了一个happens before 关系。黑色箭头表示程序顺序规则;橙色箭头表示监视器锁规则;蓝色箭头表示组合这些规则后提供的happens before保证。

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

锁释放和获取的内存语义

当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。以上面的MonitorExample程序为例,A线程释放锁后,共享数据的状态示意图如下:

深入Java内存模型之阅读理解(2)「建议收藏」

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

深入Java内存模型之阅读理解(2)「建议收藏」

 

对比锁释放-获取的内存语义与volatile写-读的内存语义,可以看出:锁释放与volatile写有相同的内存语义;锁获取与volatile读有相同的内存语义。

下面对锁释放和锁获取的内存语义做个总结:

  • 线程A释放一个锁,实质上是线程A向接下来将要获取这个锁的某个线程发出了(线程A对共享变量所做修改的)消息。
  • 线程B获取一个锁,实质上是线程B接收了之前某个线程发出的(在释放这个锁之前对共享变量所做修改的)消息。
  • 线程A释放锁,随后线程B获取这个锁,这个过程实质上是线程A通过主内存向线程B发送消息。

 

ReentrantLock的实现:

class ReentrantLockExample {
int a = 0;
ReentrantLock lock = new ReentrantLock();

public void writer() {
    lock.lock();         //获取锁
    try {
        a++;
    } finally {
        lock.unlock();  //释放锁
    }
}

public void reader () {
    lock.lock();        //获取锁
    try {
        int i = a;
        ……
    } finally {
        lock.unlock();  //释放锁
    }
}
}

 

在ReentrantLock中,调用lock()方法获取锁;调用unlock()方法释放锁。

ReentrantLock的实现依赖于java同步器框架AbstractQueuedSynchronizer(简称之为AQS)。

AQS使用一个整型的volatile变量(命名为state)来维护同步状态。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/107799.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 转:谷歌离线地图基础[通俗易懂]

    转:谷歌离线地图基础[通俗易懂]一.需要文件gapi3文件夹:存放接口等tilemap文件夹:存放图片gapi.js文件maptool.js文件二.html配置<scripttype="text/javascript"src="gapi.js"></script><scripttype="text/javascript"src="maptool.js">&lt

  • Linux环境MySQL卸载教程「建议收藏」

    Linux环境MySQL卸载教程「建议收藏」Linux环境MySQL卸载

  • C++ 顶层 const

    C++ 顶层 const

  • activiti7实战教程(一)集成用户系统

    activiti7实战教程(一)集成用户系统新建SpringBoot项目版本号2.6.3 <?xmlversion=”1.0″encoding=”UTF-8″?><projectxmlns=”http://maven.apache.org/POM/4.0.0″xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0https://maven.a

  • lm算法的实现方法_信赖域算法

    lm算法的实现方法_信赖域算法完整文章请查看这里。转载请注明出处:本文来自learnhard的博客:http://www.codelast.com/ & http://blog.csdn.net/learnhard/,并保持文章的完整性。 LM算法可用于解决非线性最小二乘问题。多用于曲线拟合等场合。LM算法的实现并不难,这里不讨论使用MATLAB等工具直接得到结果的过程,使用那些工具对于算法编程能力的提高无任何益处。 LM算法

  • IDEA激活成功教程后一直提示JetbrainsAgent 相关的弹框问题

    IDEA激活成功教程后一直提示JetbrainsAgent 相关的弹框问题激活成功教程后打开IDEA就弹框,关闭之后会自动打开浏览器,隔一会也会弹出来 也是一样的问题一开始是说把txt 和 jar 文件放一个路径下之类的方法,几经波折,发现没任何用处~最后各种搜索排查,在设置下更改配置就不弹啦~settings设置下搜索agent 取消”Instrumenting agent(requires debugger restart)”在 Reload classes after compilation:选择第一个 Always…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号