深入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 happens before 2, 2 happens before 3; 4 happens before 5, 5 happens before 6。
- 根据监视器锁规则,3 happens before 4。
- 根据happens before 的传递性,2 happens before 5。
上述happens before 关系的图形化表现形式如下:

在上图中,每一个箭头链接的两个节点,代表了一个happens before 关系。黑色箭头表示程序顺序规则;橙色箭头表示监视器锁规则;蓝色箭头表示组合这些规则后提供的happens before保证。
上图表示在线程A释放了锁之后,随后线程B获取同一个锁。在上图中,2 happens before 5。因此,线程A在释放锁之前所有可见的共享变量,在线程B获取同一个锁之后,将立刻变得对B线程可见。
锁释放和获取的内存语义
当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。以上面的MonitorExample程序为例,A线程释放锁后,共享数据的状态示意图如下:

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

对比锁释放-获取的内存语义与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)来维护同步状态。
深入Java内存模型之阅读理解(2)的更多相关文章
- 深入Java内存模型之阅读理解(1)
Java内存模型的抽象 在java中,所有实例域.静态域和数组元素存储在堆内存中,堆内存在线程之间共享(本文使用“共享变量”这个术语代指实例域,静态域和数组元素).局部变量(Local variabl ...
- java内存模型原理阅读总结
Java内存模型可以理解为在特定操作协议下,对特定的内存或高速缓存进行读写访问的过程抽象.不同架构的物理计算机可以有不一样的内存模型,java虚拟机也有自己的内存模型,java虚拟机规范中试图定义一种 ...
- java内存模型:简单理解
1.Java内存模型(Java Memory Model,JMM) 2.JMM定义了线程和主内存之间的抽象关系: 线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地 ...
- Java内存模型的深入理解
基础 并发编程的模型分类 在并发编程需要处理的两个关键问题是:线程之间如何通信 和 线程之间如何同步. 通信 通信 是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信机制有两种:共享内存 ...
- 《成神之路-基础篇》JVM——Java内存模型(已完结)
Java内存模型 本文是<成神之路系列文章>的第一篇,主要是关于JVM的一些介绍. 持续更新中 Java内存模型 JVM内存结构 VS Java内存模型 VS Java对象模型(Holli ...
- 《Java并发编程实战》第十六章 Java内存模型 读书笔记
Java内存模型是保障多线程安全的根基,这里不过认识型的理解总结并未深入研究. 一.什么是内存模型,为什么须要它 Java内存模型(Java Memory Model)并发相关的安全公布,同步策略的规 ...
- Java并发(二):Java内存模型
一.硬件内存架构 一个现代计算机通常由两个或者多个CPU.其中一些CPU还有多核.每个CPU在某一时刻运行一个线程是没有问题的.如果你的Java程序是多线程的,在你的Java程序中每个CPU上一个线程 ...
- 并发编程-Java内存模型
将之前看过的关于并发编程的东西总结记录一下,本文简单记录Java内存模型的相关知识. 1. 并发编程两个关键问题 并发编程中,需要处理两个关键问题:线程之间如何通信及线程之间如何同步. (1)在命令式 ...
- Java并发编程:Java内存模型JMM
简介 Java内存模型英文叫做(Java Memory Model),简称为JMM.Java虚拟机规范试图定义一种Java内存模型来屏蔽掉各种硬件和系统的内存访问差异,实现平台无关性. CPU和缓存一 ...
随机推荐
- C++ 代码格式化工具Astyle
1.下载Asyle程序. win版本:https://sourceforge.net/projects/astyle/ 2.将bin/AStyle.exe拷到源码目录中,在命令行终端执行. AStyl ...
- mysql5.7报err 1055错误 sql_mode=only_full_group_by
vim /etc/my.cnf 末尾增加 sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_B ...
- cocos2d-x项目创建和打包
1.创建C++的cocos2d-x项目:cocos new test_cpp02 -p com.benmutou.helloWorld -l cpp -d projects C++未编译目录: C++ ...
- 出现System.web.mvc冲突的原因及解决方法CS0433
1.问题描述 CS0433:类型“System.Web.Mvc.WebViewPage<TModel>”同时存在于URL1和URL2中 2.解决方案 找到Web.config文件中的< ...
- eclipse-在编译项目时js特别慢的问题
eclipse在编译项目时,当项目中导入了很多第三方js库时,eclipse在验证js时会消耗大量的时间,而我们却完全不用考虑那些js是否有错误 步骤: 去除eclipse的JS验证: 1.将wind ...
- sprintf将CString转换成char[]
在MFC中使用sprintf()函数将CString转换成char[]时,char[]只接受第一个字符 使用的是VS2008 CString name;dbName="test" ...
- js获取客户端time,cookie,url,ip,refer,user_agent信息:
<script src="http://pv.sohu.com/cityjson?ie=utf-8"></script> <script type=& ...
- XMR恶意挖矿脚本处理笔记
一.登录 攻击者如何登录系统未能查出,所有日志已被清除.为防万一,把系统中没用的用户都删掉并修改其他用户密码. 二.被攻击后的表象 1.服务器资源被大量占用,资源占用率飙升: 2.服务器所有JS文件被 ...
- 使用LinkedHashMap来实现一个使用LRU(Least Recently Used)算法的cache
removeEldestEntry在使用put或者putAll方法插入一个新的entry到map中时被调用,是否要删除年老的entry取决于是否满足既定的条件(比如本例中的条件:MAP中entry数量 ...
- Attempt to present <TestViewController2: 0x7fd7f8d10f30> on <ViewController: 0x7fd7f8c054c0> whose view is not in the window hierarchy!
当 storyboard里面的 按钮 即连接了 类文件里面的点击方法 又 连接了 storyboard里 另一个 控制器的 modal 就会出现类似Attempt to present & ...