一 引言

  在说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内存模型-锁的内存语义的更多相关文章

  1. Java内存模型-volatile的内存语义

    一 引言 听说在Java 5之前volatile关键字备受争议,所以本文也不讨论1.5版本之前的volatile.本文主要针对1.5后即JSR-133针对volatile做了强化后的了解. 二 vol ...

  2. java内存模型-锁

    锁的释放-获取建立的 happens before 关系 锁是 java 并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息.下面是锁释放-获取的示 ...

  3. 【java】java内存模型(2)--volatile内存语义详解

    多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”.可见性的意思是当一个线程 ...

  4. Java 内存模型和硬件内存架构笔记

    前言 可跟<主存存取和磁盘存取原理笔记>串着看 https://blog.csdn.net/suifeng3051/article/details/52611310 杂技 Java 内存模 ...

  5. Java并发编程里的volatile。Java内存模型核CPU内存架构的对应关系

    CPU内存架构:https://www.jianshu.com/p/3d1eb589b48e Java内存模型:https://www.jianshu.com/p/27a9003c33f4 多线程下的 ...

  6. JAVA内存模型与JVM内存结构

    问题:什么事java内存模型? 首先呢不要答堆.栈.方法区.这是JVM的内存结构.下面阐述了JMM和JVM的区别和自己对JMM的见解 1.Java内存模型(JMM):即多线程相关的.定义了一个线程对另 ...

  7. Java内存模型、JVM内存结构和Java对象模型

    JVM内存结构 我们都知道,Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途.其中有些区域随着虚拟机进程的启动而存 ...

  8. 内存模型 Memory model 内存分布及程序运行中(BSS段、数据段、代码段、堆栈

    C语言中内存分布及程序运行中(BSS段.数据段.代码段.堆栈) - 秦宝艳的个人页面 - 开源中国 https://my.oschina.net/pollybl1255/blog/140323 Mem ...

  9. 04-JVM内存模型:直接内存

    1.1.什么是直接内存(Derect Memory) 在内存模型最开始的章节中,我们画出了JVM的内存模型,里面并不包含直接内存,也就是说这块内存区域并不是JVM运行时数据区的一部分,但它却会被频繁的 ...

随机推荐

  1. Linux内核分析 一二章读书笔记

    第一章 Linux内核简介 1.Unix (1)Unix系统很简洁 (2)在Unix中,所以东西都被当作文件对待,通过一套相同的系统调用接口来进行:open(),read(),write(),lsee ...

  2. 打包spring项目遇到的坑 Unable to locate Spring NamespaceHandler for XML schema ……shcema/context 产生的原因及解决方法

    图1 图2 问题原因:导致该问题的原因就是打包的时候,同时将 spring-context 和 spring-aop包提取到了我们的程序应用的包中,在package过程中,这2个依赖包的 XML sc ...

  3. Linux命令(二十七) 用户组管理命令

    Linux提供了一系列的命令管理用户组.用户组就是具有相同特征的用户集合.每个用户都有一个用户组,系统能对一个用户组中所有用户进行集中管理,通过把相同属性的用户定义到同一用户组,并赋予该用户自一定的操 ...

  4. sqlserver 比较两个表的列

    一.问题 给了两个各有四五十个列的表,找出他们相同的列和不同的列 二.查询两个表的列,存在临时表 --#a ,#b都是临时表,当前连接断开后自动删除--RANK() OVER (ORDER BY sy ...

  5. 二分图最大权匹配模板(pascal)

    用uoj80的题面了: 从前一个和谐的班级,有 nlnl 个是男生,有 nrnr 个是女生.编号分别为 1,…,nl1,…,nl 和 1,…,nr1,…,nr. 有若干个这样的条件:第 vv 个男生和 ...

  6. DBA 这个角色

    下面这些领域的技能可以提升DBA团队对公司业务产生正面影响的重要能力: ---------------------------------------------------------------- ...

  7. 2017-2018 ACM-ICPC, Asia Daejeon Regional Contest C(记忆化搜索)

    C题 Problem C Game Map 思路: 之前暴力搜索写了好几发,一直超时,后面看其他人的题解发现要用记忆化搜索..直接暴力搜的话有太多重 复的计算. dist u 表示以u 为起点所能走的 ...

  8. MT【172】内外圆

    $P,Q$是两个定点,M为平面内一个动点,且$\dfrac{|MP|}{|MQ|}=\lambda(\lambda>0,\lambda\ne1)$, 点M的轨迹围成的区域面积为S , 设$S=f ...

  9. Kakfa的设计思想

    Kafka Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实 ...

  10. Mountainous landscape

    Description 现在在平面上给你一条折线 \(P_1P_2 \cdots P_n\) . \(x\) 坐标是严格单调递增的.对于每一段折线 \(P_iP_{i+1}\) ,请你找一个最小的 \ ...