标签:Java monitor synchronized 线程 内存 NULL 浅析 底层
synchronized 是 Java 的关键字之一,提供一种原子性的内部锁,Java 中的每个对象都可以把它当作一个同步锁使用,这种 Java 内置的使用者看不到的锁为内部所,或叫监视器锁。
目录synchronized 内存语义
进入 synchronized
块,即是当前线程会从自己的工作内存中清除 synchronized
块中使用到的变量,并从主内存中加载。
退出 synchronized
块,即是当前线程将对 synchronized
块中使用到的变量作出的修改刷新到主存上。
Monitor
简介
即上述所提到的监视器锁中的监视器(monitor),也会被翻译为管程。在操作系统中,面对多线程操作时,通常会用到 semaphore
(信号量)和mutex
(互斥)这两个重要的同步原语,但直接操作这两者会非常复杂。为了能够更容易编写正确程序,在二者的基础上,提出了monitor
。
需要注意,操作系统本身不支持monitor
,monitor
的支持属于编程语言范围,例如 C 语言不支持monitor
,而 Java 是支持的。对于不同语言,monitor
的实现方式也不一样。
monitor
的发展史上,有三种不同的模型:
- Hasen模型
- Hoare模型
- MESA模型
后面提到的 monitor
均指 Java 中实现的 monitor
Java 则参考了 MESA 模型进行实现,在 JVM 使用的 HostSpot 模拟机中,monitor
是由 C++ 来实现的,主要数据结构如下:
ObjectMonitor() {
_header = NULL;
_count = 0; //monitor进入数
_waiters = 0,
_recursions = 0; //线程的重入次数
_object = NULL;
_owner = NULL; //标识拥有该monitor的线程
_WaitSet = NULL; //等待线程组成的双向循环链表,_WaitSet是第一个节点
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ; //多线程竞争锁进入时的单项链表
FreeNext = NULL ;
_EntryList = NULL ; //处于等待锁block状态的线程,会被加入到该列表
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}
使用 synchronized
关键字,通常需要指定一个对象,称作monitor object
。HotSpot 会自动创建与该对象关联的monitor
对象。
特点
同一时刻,monitor
仅支持一个 进程 / 线程进入monitor
定义的临界区(达成互斥)。同时,还需要对未能进入临界区的 进程 / 线程 进行管理,例如 阻塞 和 唤醒。monitor
作为一个同步工具,能够提供管理 进程 / 线程状态的机制。
如若
semaphore
(信号量)和mutex
(互斥),还需要使用者对上述机制进行实现,而monitor
在内部进行了实现,对外提供了更简洁易用的接口。
当线程需要获取锁时,会放入 Entry Set
进行等待。
如果线程得到锁,则称为当前锁的Owner
。
若获得锁的线程运行时发现需要等待外部条件,则可调用wait
方法,进入Wait Set
等待。
进入Wait Set
的线程会被notify
的调用唤醒,重新尝试获取锁变为Owner
。
还需要留意一点时,线程出入临界区时,会分别执行moniterenter
/moniterexist
系统调用,同时 Java 线程实际上是对操作系统线程的映射。因此在 Java SE1.6 前,使用synchronized
会造成线程状态切换(用户态和内核态),增大运行开销。在 Java SE1.6 后,synchronized
得到优化,引入了 偏向锁、轻量级锁。
对象内存模型中的锁标记
在此,需要了解一下 Java 对象的内存模型,Java 的对象构成有三部分:
- 对象头:包含 Mark Word(标记)、Class Pointer (类信息)
- 实例数据
- 对齐填充
其中对象头的 MarkWord 共 32 bit ,包含了锁的状态信息,可见 Mark Word 中包含了四种锁状态:
- 无锁
- 偏向锁
- 轻量级锁
- 重量级锁
锁会根据竞争条件的不同进行对应上面四种状态,由上至下进行升级,且不能降级。
锁升级过程可以参考:https://www.bilibili.com/video/BV1xT4y1A7kA?spm_id_from=333.999.0.0
参考链接
https://blog.csdn.net/TZ845195485/article/details/108099961
https://blog.csdn.net/qq_36934826/article/details/95978700
https://www.cnblogs.com/wade-luffy/p/5969418.html
标签:Java,monitor,synchronized,线程,内存,NULL,浅析,底层 来源: https://www.cnblogs.com/Dozeer/p/15477427.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。