多线程
2024-12-28 17:45:45 0 举报
多线程
作者其他创作
大纲/内容
创建新的线程执行任务
next
state-1
共享变量
firstWaiter
入队
thread = B
挂起
不相等
锁重入state+1
thread = 03
thread = A
尝试加读锁
对象引用地址
Thread-05
否
返回false解锁失败
是
thread = null
00:轻量级锁
锁记录
自旋
Thread-01
不是
thread = 05
Thread执行到同步代码块
实例数据
否:加锁失败
判断锁有没有被占用
Klass
waitStatus = -1
thread = C
为当前线程栈中分配锁记录
object
执行同步代码块内容
判断加锁次数是否为0
分代年龄
开始释放重量级锁
加锁成功
Thread-02
对齐填充
成功:锁对象的Markword是当前线程锁记录的地址
判断第一个加读锁的线程读锁数量是否等于1
判断当前计数值是否为0
已满
非公平锁
Epoch
公平锁
tail
锁记录自身地址
判断是否有资格竞争锁
01:无锁/偏向锁
抛出异常
判断是否有竞争锁的资格
state = 3
读锁计数器锁重入数量减一
01
先获取读锁状态
state =1
prev
Mark Word
waitStatus = -2
根据加锁之前获取的读锁状态是否为0
成功
设置独占线程为当前线程
waitStatus = 0
加锁失败
失败
判断当前计数值是否小于1
有
唤醒后的线程开始自旋
thread = 02
判断队列是否已初始化
更新state值
创建node节点入队尾
判断第一个读锁线程是否是当前线程
10:重量锁
提交任务
判断计数器是否为空
返回true解锁成功
解锁unlock
判断锁的标志位
head
1
返回-1加锁失败
唤醒原持有偏向锁,现持有轻量锁的线程,挂起自身线程
线程1
原持有偏向锁的线程运行到安全点
判断当前线程id是自己
当前线程挂起,等待唤醒
Thread-04
Monitor的Owner指向当前拥有轻量级锁的线程,本线程进入Monitor的EntryList 挂起
升级为重量级锁
被唤醒的节点在挂起的地方继续执行
当前线程获得轻量锁
ReentrantLock
Thread-03
JMM控制
_EntryList
没有
CAS操作替换线程id
lastWaiter
exclusiveOwnerThread
获取缓存计数器
未满
为原持有偏向锁的线程栈中分配锁记录
判断持有写锁的是否是当前线程
判断下一个节点是否共享类型节点
是:唤醒下一个节点
出队
cas操作修改state尝试加锁
当前计数值+1
00
唤醒前驱节点为头节点的线程
判断阻塞队列是否满
将计数器移出缓存中
拷贝对象头的markWord到原持有偏向锁的锁记录
执行拒绝策略
主内存
工作内存
开始撤销偏向状态
再次尝试
原持有偏向锁,现持有轻量锁的线程执行完同步代码块
未初始化
失败:锁对象的Markword是当前线程锁记录的地址,比如变成了monitor地址
判断当前线程是否是持有锁的线程
0:无锁
共享变量副本
未退出
自旋一定次数后还未成功
signal
重入次数+1
暂停原持有偏向锁线程
自身变成头节点,原头节点出队
判断计数器是否是当前线程的
ReentrantReadWriteLock
判断state是否等于0
加锁的次数-1
拥有轻量级锁的线程获取/升级为重量级锁
获取当前线程缓存计数器
唤醒Monitor队列中挂起的线程
nextWaiter
返回1加锁成功
synchronized锁的对象引用地址
Mark Word
判断是否是第二个节点
线程池
判断state是否为0
将对象头恢复成无锁状态
结束
将任务添加到阻塞队列中
判断是否可以挂起
再尝试加锁:tryAcquire(1)
线程id
当前线程获得重量级锁
判断当前运行的线程数是否小于maximumPoolSize
CAS操作替换锁对象的markword为当前线程锁记录的地
将计数器移出缓存
第一个读锁线程计数+1
判断是否超过最大重入次数
state = 1
ReadLock的unlock()
第一个读锁线程计数=1
monitor地址
将计数器存入缓存中
已初始化
不等于,发生了锁重入
唤醒头节点的下一个节点
ReadLock的lock()
,,,,
CAS成功
当前线程设置为第一个读锁线程
判断占用锁的是否是自己
尝试加锁:tryAcquire(1)
相等:等待队列没有线程了
_owner
判断读锁数量是否超过最大值
判断是否第二个节点
shouldParkAfterFailedAcquire方法,在挂起之前,判断/查找/设置前驱节点是waitStatus = -1
第一个加读锁的线程读锁数量减一
判断原持有偏向锁的线程是否已退出同步代码块
CAS操作
判断头节点和尾节点是否相等
退出
CAS失败
可以:被唤醒的节点继续自旋
判断是否存在写锁
parkAndCheckInterrupt方法,挂起当前线程
CAS操作替换markword
执行同步代码块
否:锁升级
state = 0
加锁lunck
WriteLock的unlock()
10
判断是否是偏向锁
线程2
判断当前运行的线程数是否少于corePoolSize
设置独占线程为null
cas操作更改state值
锁升级
释放锁
原持有偏向锁,现持有轻量锁的线程继续执行同步代码块
......线程n
exclusiveOwnerThread置空state置为0,解锁成功
判断写锁是否为0
初始化队列
升级为轻量级锁
为锁对象申请Monitor锁,让锁对象markword指向Monitor
多次尝试仍失败
判断阻塞队列的第二节点是否可以唤醒
判断前驱节点是否是头节点
判断拥有写锁线程是否是当前线程
判断当前线程是否是第一个加读锁的线程
轻量锁
await
null
WriteLock的lock()
挂起被唤醒
原持有偏向锁的线程获取轻量锁
判断写锁的值是否为0
新一轮竞争锁
第一个加读锁的线程
再次尝试获取锁
等于
_WaitSet
开始释放轻量锁
1:偏向锁
0 条评论
下一页