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发送消息 。
Java中锁的内存语义的更多相关文章
- Java中锁的实现与内存语义
目录 1. 概述 2. 锁的内存语义 3. 锁内存语义的实现 4. 总结 1. 概述 锁在实际使用时只是明白锁限制了并发访问, 但是锁是如何实现并发访问的, 同学们可能不太清楚, 下面这篇文章就来揭开 ...
- volatile 和锁的内存语义
一.volatile 的内存语义 1. volatile 的特性 volatile变量自身具有以下特性: 可见性 :对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后 ...
- JAVA中锁的解决方案
前言 在上一节中,我们给大家介绍了什么是锁,以及锁的使用场景,我相信大家对锁的定义,以及锁的重要性都有了比较清晰的认识.在这一节中,我们会给大家继续做深入的介绍,介绍JAVA为我们提供的不同种类的锁. ...
- Java宝典(四)------Java中也存在内存泄露。
--Java中会存在内存泄露吗? --如果你想当然的以为Java里有了垃圾回收机制就不会存在内存泄露,那你就错了. Java里也会存在内存泄露! 我们慢慢来分析. 所谓内存泄露就是指一个不再被程序使用 ...
- Java 中数组的内存分配
Java 中数组的内存分配 1.Java 程序在运行时,需要在内存中分配空间.为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据和内存管理方式. 2.数组基本概念 数组是 ...
- Java基础-Java中的堆内存和离堆内存机制
Java基础-Java中的堆内存和离堆内存机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.
- Java中会存在内存泄露吗?请简单描述。
本文转载自:Java中会存在内存泄漏吗,请简单描述 会.java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周 ...
- java中JVM虚拟机内存模型详细说明
java中JVM虚拟机内存模型详细说明 2012-12-12 18:36:03| 分类: JAVA | 标签:java jvm 堆内存 虚拟机 |举报|字号 订阅 JVM的内部结构 ...
- 并发王者课-铂金1:探本溯源-为何说Lock接口是Java中锁的基础
欢迎来到<并发王者课>,本文是该系列文章中的第14篇. 在黄金系列中,我们介绍了并发中一些问题,比如死锁.活锁.线程饥饿等问题.在并发编程中,这些问题无疑都是需要解决的.所以,在铂金系列文 ...
随机推荐
- luogu P1057 传球游戏
题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每个同 ...
- javascript好文---深入理解定位父级offsetParent及偏移大小
前面的话 偏移量(offset dimension)是javascript中的一个重要的概念.涉及到偏移量的主要是offsetLeft.offsetTop.offsetHeight.offsetWid ...
- Apple激活日期查询
需要输入的信息为苹果产品的序列号 查看您的保修服务和支持期限 - Apple 支持 或者通过果粉查询网站获取结果
- Android开发——内存优化 图片处理
8. 用缓存避免内存泄漏 很常见的一个例子就是图片的三级缓存结构,分别为网络缓存,本地缓存以及内存缓存.在内存缓存逻辑类中,通常会定义这样的集合类. private HashMap<Strin ...
- DevExpress.XtraGrid 【转】
http://www.cnblogs.com/zeroone/p/4574539.html DevExpress.XtraGrid控件使用 该控件类是一个表格控件,但是其具有很多方便而使用的功能,例如 ...
- vdWebControl.js去水印
vdWebControl.js可以在浏览器中展示cad图形(须要使用其自家的转换工具把cad转换为vds格式.工具免费,但转换完成后的文件带水印信息),支持编辑图形. vdWebControl.js试 ...
- discuz X3.1+Apache2.2+php-5.2.17+mysql5.6.14+Discuz_X3.1
discuz X3.1+Apache2.2.25+php-5.2.17+mysql5.6.14+Discuz_X3.1 一.准备 1.httpd-2.2.25-win32-x86-no_ssl.msi ...
- [3 Jun 2015 ~ 9 Jun 2015] Deep Learning in arxiv
arXiv is an e-print service in the fields of physics, mathematics, computer science, quantitative bi ...
- python 调用函数时使用星号 *, **
python 调用函数时使用星号 *, ** 调用函数时使用星号 * 或 ** test(*args):* 的作用其实就是把序列 args 中的每个元素,当作位置参数传进去.如果 args 等于 (1 ...
- FastDFS的配置、部署与API使用解读(8)FastDFS多种文件上传接口详解(转)
1.StorageClient与StorageClient1的区别 相信使用happy_fish的FastDFS的童鞋们,一定都熟悉StorageClient了,或者你熟悉的是StorageClien ...