一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情
什么是锁
互斥:规定同一时间内多个线程只能有一个线程能够持有监视器,其他线程不能进入由监视器保护的同步块,直到那一个线程退出监视器
可见性:当获取锁的时候,线程的CPU会强制从主存中获取最新值,当释放锁的时候,会将CPU的缓存行刷回主存中。
下图为sync的hapends-before关系图,
红线为监视器锁规则推导,蓝线为程序顺序推导。
这样意味着线程A的操作对线程B是可见的,前面线程执行的结果对后面线程是可见的,那么对于线程来说就是线程间相互通信。
monitor
基于进出ObjectMonitor对象来实现同步。任何对象都有monitor。
-
同步代码块:使用monitorenter和monitorexit指令实现。
-
在编译后monitorenter插入到同步代码块的开始位置
-
monitorexit插入到同步代码块结束位置和异常位置
-
同步方法:编译中flags指定为ACC_SYNCHRONIZED,那么线程在执行方法前会先去获取monitor对象
什么是monitor
操作系统的管程,一种同步机制,管理多线程互斥访问共享资源,即同一时间点,只有一个线程能够访问共享资源。ObjectMonitor是其实现。
对象存在着一个monitor与其对应->Objectmonitrot对象,将mark word存储指向这个对象的地址,将mark word锁标志为设置为10
下图为ObjectMonitor对象的属性。
-
_header : 存放对象的mark word的hashCode,分代年龄,偏向锁标志为等信息30bit
-
_owner : 指向当前持有锁的线程
-
_recursions:锁重入的次数
-
_count:用来记录该线程获取锁的次数。调用monitorenter使其+1,monitorexit使其-1
-
_waitSet(等待队列)
- waitSet用于存储调用wait() 等待唤醒的线程。当调用wait()后释放锁,将该线程存入waitSet中,当线程被notify()通知,就会进入EntrySet竞争锁。因为每一个对象都能当锁,因此wait和notify是Object的方法
-
_EntryList(阻塞(同步)队列)
- EntrySet用于存储等待竞争锁的线程