Java内存模型-锁的内存语义
一 引言
在说volatile的内存语义时,讲过这样一句话:想要理解透volatile特性有一个很好的方法,就是把对volatile变量的单个读/写,看成是使用同一个锁对这些单个读/写操作做了同步。所以其实锁的释放和获取与volatile的写和读具有相同的内存语义。
二 锁的释放-获取建立的happens-before关系
不清楚happens-before规则的请前去看-看,这里就不在细说了。由于在之前没有举例说明监视器锁规则,那么在这里就详细说明下,下面是锁释放-获取的示例代码:
public class MonitorExample {
int a = 0;
public synchronized void writer() { //
a += 1; //
} //
public synchronized void reader() { //
System.out.println(a); //
} //
public static void main(String[] args) {
final MonitorExample me = new MonitorExample();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
me.writer();
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
me.reader();
}
});
t2.start();
}
}
这里我们假设线程1先执行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关系的图形化表现形式如下:

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

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

对比锁释放-读取的内存语义与volatile写-读的内存语义可以看出,锁释放与volatile写具有相同的内存语义;锁获取与volatile读具有相同的内存语义。下面对锁释放和锁获取的内存语义做个总结。
- 线程1释放一个锁,实质上是线程1向接下来将要获取这个锁的某个线程发出了(线程1对共享变量所做修改的)消息。
- 线程2获取一个锁,实质上是线程2接收了之前某个线程发出的(在释放这个锁之前对共享变量所做修改的)消息。
- 线程1锁释放,随后线程2获取这个锁,这个过程实质上是线程A通过主内存向线程B发送消息。
四 锁内存语义的实现
锁有很多种,但其基本原理都是差不多的。书上是以ReentrantLock中的公平锁与非公平锁作为案例分析,有兴趣的同学可以去阅读原籍和源码。现总结如下:
- 公平锁和非公平锁释放时,最后都要写一个volatile变量state。
- 公平锁获取是,首先会去读volatile变量。
- 非公平锁获取时,首先会用CAS更新volatile变量,这个操作同时具有volatile读和写的内存语义。
所以锁释放-获取的内存语义的实现至少有下面两种方式:
1)利用volatile变量的写-读所具有的内存语义。
2)利用CAS所附带的volatile读和volatile写的内存语义。
由此可知:并发包下的类的实现方式大部分都是基于这两种方式实现的。
Java内存模型-锁的内存语义的更多相关文章
- Java内存模型-volatile的内存语义
一 引言 听说在Java 5之前volatile关键字备受争议,所以本文也不讨论1.5版本之前的volatile.本文主要针对1.5后即JSR-133针对volatile做了强化后的了解. 二 vol ...
- java内存模型-锁
锁的释放-获取建立的 happens before 关系 锁是 java 并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息.下面是锁释放-获取的示 ...
- 【java】java内存模型(2)--volatile内存语义详解
多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”.可见性的意思是当一个线程 ...
- Java 内存模型和硬件内存架构笔记
前言 可跟<主存存取和磁盘存取原理笔记>串着看 https://blog.csdn.net/suifeng3051/article/details/52611310 杂技 Java 内存模 ...
- Java并发编程里的volatile。Java内存模型核CPU内存架构的对应关系
CPU内存架构:https://www.jianshu.com/p/3d1eb589b48e Java内存模型:https://www.jianshu.com/p/27a9003c33f4 多线程下的 ...
- JAVA内存模型与JVM内存结构
问题:什么事java内存模型? 首先呢不要答堆.栈.方法区.这是JVM的内存结构.下面阐述了JMM和JVM的区别和自己对JMM的见解 1.Java内存模型(JMM):即多线程相关的.定义了一个线程对另 ...
- Java内存模型、JVM内存结构和Java对象模型
JVM内存结构 我们都知道,Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途.其中有些区域随着虚拟机进程的启动而存 ...
- 内存模型 Memory model 内存分布及程序运行中(BSS段、数据段、代码段、堆栈
C语言中内存分布及程序运行中(BSS段.数据段.代码段.堆栈) - 秦宝艳的个人页面 - 开源中国 https://my.oschina.net/pollybl1255/blog/140323 Mem ...
- 04-JVM内存模型:直接内存
1.1.什么是直接内存(Derect Memory) 在内存模型最开始的章节中,我们画出了JVM的内存模型,里面并不包含直接内存,也就是说这块内存区域并不是JVM运行时数据区的一部分,但它却会被频繁的 ...
随机推荐
- 2-Twelfth Scrum Meeting20151212
任务安排 成员 今日完成 明日任务 闫昊 获取视频播放的进度 获取视频播放进度 唐彬 解决handler可能引起的内存泄露问题 阅读IOS代码+阅读上届网络核心代码 史烨轩 下载service开发 ...
- 20135234mqy-——信息安全系统设计基础第十二周学习总结
process environ.c environvar.c consumer.c 管道写端 producer.c 管道读端 testmf.c listargs.c pipedemo.c 管道 pip ...
- Linux基础六(网络管理)
目录 一.网络配置 1. IP 地址配置 2. 网络配置文件 3. 虚拟机网络配置参数 二.网络命令 1. 网络环境查看命令 2. 网络测试命令 三.远程会话安全协议-SSH原理 1. SSH 原理 ...
- Beta冲刺——day2
Beta冲刺--day2 作业链接 Beta冲刺随笔集 github地址 团队成员 031602636 许舒玲(队长) 031602237 吴杰婷 031602220 雷博浩 031602134 王龙 ...
- [转帖] mysql 用户 权限 密码等操作记录
前言 From :https://blog.csdn.net/yu12377/article/details/78214336 mysql5.7版本中用户管理与以前版本略有不同,在此记录,以备忘 登陆 ...
- AtCoder Grand Contest 030 自闭记
A:阅读. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> ...
- Day23-Model操作,Form操作和序列化操作
参考源出处:http://blog.csdn.net/fgf00/article/details/54629502 1. 搭建环境请参考:http://www.cnblogs.com/momo8238 ...
- VMXNET3 vs E1000E and E1000
VMXNET3 vs E1000E and E1000 用户为什么要从E1000调整为VMXNET3,理由如下: E1000是千兆网路卡,而VMXNET3是万兆网路卡: E1000的性能相对较低,而V ...
- 自学Zabbix10.1 Configuration export/import 配置导入导出
自学Zabbix10.1 Configuration export/import 配置导入导出 通过导入/导出zabbix配置文件,我们可以将自己写好的模板等配置在网络上分享,我们也可以导入网络上分享 ...
- 安装完打开 eclipse 提示 JVM 版本较低
在安装完 eclipse 后打开出现如下提示 解决办法: 1> 去官网下载最新版本安装 地址 2> linux 下直接下载安装 1.打开终端 2.控制台输入:su 3.控制台输入个人密码 ...