Synchronized轻量级锁源码分析
2025-02-26 15:13:49 0 举报
Synchronized轻量级锁源码分析,分享给大家学习。 更多干货内容,欢迎关注我的公众号:Fox爱分享
作者其他创作
大纲/内容
通过CAS尝试将Mark Word更新为指向Lock Record的指针,如果更新成功,表示竞争到锁
ReadStableMark(object) ;
锁膨胀的过程,该方法返回一个ObjectMonitor对象,然后调用其enter方法
false
取出栈帧中保存的mark word
true
object->release_set_mark(markOopDesc::encode(m));
Lock Record
把markword保存到BasicLock对象的_displaced_header字段
displaced word
00
轻量级锁释放真正逻辑
Object
CAS设置状态为膨胀中
CAS 设置锁对象mark word为重量级锁状态
判断当前是否为重量级锁状态,即Mark Word的锁标识位为 10,如果已经是重量级锁状态直接返回
objectMonitor.cpp#ObjectMonitor::enter
ptr_to_lock_record
obj
轻量级锁膨胀流程如下:1.调用omAlloc分配一个ObjectMonitor对象,在omAlloc方法中会先从线程私有的monitor集合omFreeList中分配对象,如果omFreeList中已经没有monitor对象,则从JVM全局的gFreeList中分配一批monitor到omFreeList中。2.初始化monitor对象3.将状态设置为膨胀中(INFLATING)状态4.设置monitor的header字段为displaced word,owner字段为Lock Record,obj字段为锁对象5.设置锁对象头的mark word为重量级锁状态,指向第一步分配的monitor对象
CASE: stack-locked
ObjectMonitor * m = omAlloc (Self) ;m->Recycle(); m->set_header(mark); m->set_owner(NULL); m->set_object(object); m->OwnerIsThread = 1 ; m->_recursions = 0 ; m->_Responsible = NULL ; m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ;
ObjectMonitor * inf = mark->monitor() ;
检查是否处于膨胀中状态(其他线程正在膨胀中),如果是膨胀中,就调用ReadStableMark方法进行等待,ReadStableMark方法执行完毕后再通过continue继续检查,ReadStableMark方法中还会调用os::NakedYield()释放CPU资源
当前轻量级锁状态,创建ObjectMonitor对象,并初始化
if (dhw == NULL)
markOop dhw = lock->displaced_header();
markOop dmw = mark->displaced_mark_helper() ;m->set_header(dmw) ; m->set_owner(mark->locker());m->set_object(object);
如果是null,说明是重入的
通过CAS尝试把dhw替换到当前的Mark Word,如果CAS成功,说明成功的释放了锁
Atomic::cmpxchg_ptr原子操作保证只有一个线程可以把指向栈帧的指针复制到Mark Word
轻量级锁 递归锁定
Mark Word
inflate中是一个for循环,主要是为了处理多线程同时调用inflate的情况
synchronizer.cpp#ObjectSynchronizer::slow_enter
锁对象
栈帧
膨胀完成返回ObjectMonitor对象
重量级锁加锁逻辑,真正的锁竞争发生在ObjectMonitor::enter方法中
null
for (;;){}
判断mark是否为无锁状态:mark的偏向锁标志位为 0,锁标志位为 01
将锁对象mark word设置为重量级锁状态
CAS失败,此时有竞争,开始膨胀
轻量级锁锁定过程1. 复制 mark word 到 displaced word2. CAS 替换 mark word 中的信息为指针3. 修改锁标志为 004. 将栈帧中的锁记录的 obj指向锁定的对象
无锁状态下的膨胀流程如下:1.调用omAlloc分配一个ObjectMonitor对象2.初始化monitor对象3.设置monitor的header字段为 mark word,owner字段为null,obj字段为锁对象4.设置锁对象头的mark word为重量级锁状态,指向第一步分配的monitor对象
获取当前锁对象的mark word
当字节码解释器执行monitorenter字节码轻度锁住一个对象时,就会在获取锁的线程的栈上显式或者隐式分配一个lock record。作用:持有displaced word和锁住对象的元数据;解释器使用lock record来检测非法的锁状态;隐式地充当锁重入机制的计数器;
获取指向ObjectMonitor的指针,并返回
有竞争CAS失败,释放monitor重试
if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker()))
CASE: inflated
CAS成功,设置ObjectMonitor的_header、_owner和_object
如果当前mark处于加锁状态,且mark中的ptr指针指向当前线程的栈帧,表示为重入操作,不需要竞争锁
这时候需要膨胀为重量级锁,膨胀前,设置Displaced Mark Word为一个特殊值,代表该锁正在用一个重量级锁的monitor
轻量级锁加锁过程
if (mark->is_neutral())
ObjectMonitor * m = omAlloc (Self) ;m->Recycle(); m->_Responsible = NULL ; m->OwnerIsThread = 0 ; m->_recursions = 0 ; m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ;
轻量级锁释放过程
synchronizer.cpp#ObjectSynchronizer::slow_exit
if (mark == markOopDesc::INFLATING())
if (mark->has_locker())
mark = object->mark() ;
mark是以下状态中的一种: Inflated(重量级锁状态) - 直接返回Stack-locked(轻量级锁状态) - 膨胀INFLATING(膨胀中) - 忙等待直到膨胀完成Neutral(无锁状态) - 膨胀 BIASED(偏向锁) - 非法状态,在这里不会出现
如果是无锁状态
直接返回
表示是重入操作,再入栈一个null到本地线程栈
ObjectSynchronizer::fast_exit
lock->set_displaced_header(mark);
将锁对象mark word设置为为重量级锁状态
if (mark->has_monitor())
CASE: inflation in progress - inflating over a stack-lock
获取锁
在该方法中会进行spin/yield/park等操作完成自旋动作
lock->set_displaced_header(markOopDesc::unused_mark())
lock->set_displaced_header(NULL);
当前是无锁状态,创建ObjectMonitor对象,并初始化

收藏

收藏
0 条评论
下一页