并发相关流程图
2021-07-12 11:37:44 0 举报
java并发相关流程总结,AQS,synchronized锁膨胀过程等
作者其他创作
大纲/内容
this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler;
新建一个队列
1(是否偏向锁)
否
无锁状态
next
将条件队列中的元素加到同步队列中并返回原来的尾结点
线程重新执行返回是否被阻断标志位
线程阻塞
node0waitStatus=-1pre=nullthread=nullnext=node1
暂停原持有偏向锁的线程
unlock释放锁
pre
thread1
waiting等待
非公平锁,先去竞争锁
是
ThreadPoolExecutor成员变量赋值
默认false
01
失败
往线程池添加任务
判断是否重入
Thread.interrupted()
其他线程就可以执行await方法了
判断是不是是否是队列中的第一个,如果是去抢占锁
LockSupport.park(this)
开始撤销偏向锁
return (E) ((mode == REQUEST) ? m.item : s.item)
非公平独占锁
compareAndSetHead(new Node())head=tail
10
nextGeneration();
terminated终止
CAS修改mark word
epoch
head
exclusiveOwnerThread=nullstatus=1
检查对象头的Mark word记录中是否是当前线程id?
判断当前线程池中的线程数量跟核心线程数的大小
唤醒线程
Node p = enq(node)
tail
return s.match
执行同步块
CyclicBarrier
唤醒原持有偏向锁的线程
获得轻量级锁指向当前线程锁记录的指针 |(标志位) 00
锁膨胀,升级为重量级锁
return remaining
lastWaiter
m.match=s;LockSupport.unpark(m.waiter)
parkAndCheckInterrupt()
当前线程
exclusiveOwnerThread=thread2status=0
mutex挂起当前线程
object的mark word
将任务放入队列
执行同步代码块
head节点的ws为0,自旋将head的ws设置为-3
加锁
lock.unlock()
加入条件队列并返回新增的节点信息
唤醒阻塞线程
tryAcquire(arg)
node2waitStatus=0pre=node1thread=线程3next=null
访问同步块
ReentrantLock lock = new ReentrantLock(true)
condition.signalAll()
指向重量级锁的monitor的指针ptr to heavyweight monitor
操作系统线程
自旋获取锁
公平独占锁
解锁成功
新增等待队列节点
LockSupport.park(this)
doAcquireSharedInterruptibly(arg)
线程3
Thread.sleep(time)
是否是正常运行结束
抢占到锁
new NonfairSync(permits)
阻塞线程2
fair为false内部的Transferer是stack实现,true则为queue实现
指向当前锁记录的指针ptr to lock record
超时时间到/join的线程运行/被中断
非公平共享锁
lock.lock()
头结点为空,或者新节点跟头结点mode一致
原持有偏向锁线程获得轻量级锁指向原持有偏向锁的线程锁记录的指针 |(标志位) 00
解锁,将Thread id置为空,偏向锁状态改为0
setState(c-1)
原持有偏向锁的线程在栈中分配锁记录
for循环一直遍历
setExclusiveOwnerThread(Thread.currentThread())
Node node = addConditionWaiter()
semaphore.release()
cyclicBarrier.await()
index == 0?
t.start()(t=worker)
runnable
线程挂起
SynchronousQueue queue = new SynchronousQueue()
ws == Node.SIGNAL
LockSupport.park(thread2)
tryAcquireShared(arg) < 0
ws=-1,一般情况下都会走这个逻辑,有新节点入队,就会将前面的节点的状态改为-1
queue.take()
command.run()
Synchronized锁升级过程
Node p = node.predecessor(); p == head && tryAcquire(arg)
挂起线程
CAS操作替换Thread id
自旋
未抢占到锁
CAS将线程数量+1
LockSupport.unpart()
fullyRelease(node)
到达安全点
重新抢占锁
未活动状态/已退出同步代码块
修改当前这个队列节点的pre的waitStatus改为1
线程1
count = parties; generation = new Generation()
成员变量重新赋值
nodewaitStatus=0pre=nullthread=thread1next=null
workers.add(w) largestPoolSize = s
在线程1上的栈上分配空间,拷贝mark word到lock record中
设置头节点为空
创建一个共享锁节点,并返回
c == 0
current == getExclusiveOwnerThread()
检查线程1是否退出同步代码块
重试
state = 3
this.parties = parties; this.count = parties; this.barrierCommand = barrierAction;
是否偏向锁?
executorService.execute(new Thread(new Runnable() { @Override public void run() { System.out.println(\"123446\"); } }));
h.next==null?
addWaiter(Node.EXCLUSIVE)
CAS失败
获取自旋次数
CAS操作将对象头中的Mark word中锁记录指针指向当前线程锁记录
前面一个节点已经处理完了
放入同步队列
CAS设置队列头部元素
头结点mode为2或者3
不是
唤醒head后面第一个线程节点
t.join()
获得偏向锁Thread id |epoch |age |(是否偏向锁)1 |(标志位) 01
升级为轻量级锁
自旋次数=0
将条件队列转成同步队列
setExclusiveOwnerThread(null)
LockSupport.unpark(thread1)
transferForSignal(first)
Worker.run()
重量级锁状态
从安全点继续执行
设置前置节点ws为-1
-
成功
拷贝对象头的Mark word到当前线程的锁记录中
this(false)
w = new Worker(firstTask)
enq(node)
在线程2上的栈上分配空间,拷贝mark word到lock record中
轻量级锁
无锁
--
偏向锁
只比较Thread id
重量级锁
依靠mutex,操作系统的互斥
可GC
用户标记GC
唤醒下一个header节点
1(是)
获取到时间片
running
tryRelease(arg)
exclusiveOwnerThread=线程1
成功返回true
selfInterrupt()
自旋到一定次数依然没有成功
LockSupport.park(this)
unparkSuccessor(h)
线程2
setHead(node)
status=1
Semaphore semaphore = new Semaphore(3)
Node node=addWaiter(Node.EXCLUSIVE)
状态
获得了monitor锁
!timed
唤醒匹配被阻塞的线程
condition.await()
将head节点的ws设置为0
ExecutorService线程池
Runnable task = w.firstTasktask ==null || task = getTask()task.run()
初始化
tryReleaseShared(arg)
将新建的工作线程加入线程池
结束
int index = --count
非公平独占锁过程图
升级为轻量级锁状态或恢复成无锁状态
timed waiting超时等待
Node pred = tail; if (pred != null)
升级为重量级锁指向重量级锁的monitor的指针 |(标志位)10
Node node = addWaiter(Node.SHARED)
r >= 0
Lock lock = new ReentrantLock(); Condition condition = lock.newCondition();
Node h = head unparkSuccessor(h)
修改失败
执行for循环逻辑
未抢占到锁,到队列中等待
释放锁
检查原持有偏向锁线程状态
特征
nonfairTryAcquireShared(acquires)
唤醒原持有偏向锁线程
0(是否偏向锁)
sync.acquireSharedInterruptibly(1)
Condition
isRunning(c) && workQueue.offer(command)
执行拒绝策略
LockSupport.parkNanos(timeout)
唤醒被挂起的那些线程
Thread w = Thread.currentThread()
m.tryMatch(s)
时间片到了/yield()方法
setState(c + 1)
sync.release(1)
!completedAbruptly
重新去获取锁
重量级锁10(标志位)
LockSupport.unpark(s.thread)
s.match!=null
Thread.currentThread().interrupt()
transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
nodewaitStatus=-1pre=nullthread=nullnext=null
线程访问同步代码块
00
waitStatus=-2thread=线程0nextWaiter=null
nodewaitStatus=-1pre=nullthread=thread1next=null
node1waitStatus=-1pre=nullthread=nullnext=node2
nonfairTryAcquire(acquires)
精髓:判断head是否变化,如果有变化继续唤醒head后面的节点
直接加新建的节点放入队尾
age
将lock中的status减到0
blocked阻塞
nanos > spinForTimeoutThreshold
h == null || h.mode == mode
exclusiveOwnerThread=thread3status=0
0(否)
原持有偏向锁的线程到达安全点
t.join(timeout)
01(标志位)
开始新一轮的锁竞争
初始化线程池
s.waiter == null
exclusiveOwnerThread=thread1status=0
workerCountOf(c) >= min
判断tail为否为空
s.waiter = w
Mark word
LockSupport.parkUntil(timeout)
挂起该线程
获取锁成功
h == head?
轻量级锁状态
return true
o.notify()
设置节点ws为0
thread2
同非公平锁解锁过程
当前线程池的数量是否大于最小的值
new新建
runWorker(this)
原持有偏向锁的线程释放锁空 |(是否偏向锁)0 |(标志位) 01
join的线程运行/被中断
setExclusiveOwnerThread(current)
拷贝对象头的Mark word到原持有偏向锁线程的锁记录中
LockSupport.unpark(s.thread)
(h = head) != null && h.next == s
检查thread id是否为线程2
lock.lock()
workerCountOf(c) < corePoolSize
lock.newCondition().await()
read
LockSupport.unpark(thread2)
构造方法中如果有设置执行线程,在这里会执行
取出工作线程中绑定的任务,如果任务为空,就去队列中取一个,通过方法执行任务的run方法
竞争synchronized锁没拿到
reject(command)
doSignalAll(first)
int spins = (shouldSpin(s) ?(timed ? maxTimedSpins : maxUntimedSpins) : 0)
ExecutorService executorService = Executors.newCachedThreadPool()
ReentrantLock lock = new ReentrantLock()
进入一个线程,信号量减1
CAS操作1&21.对象头中的Mark word中的锁记录指针是否仍然指向当前线程锁记录2.拷贝当前线程锁记录的Mark word信息是否与对象头中Mark word信息一致
将对象头的Thread id指向线程1
11
doReleaseShared()
目前锁状态?
doReleaseShared()
没有竞争到锁,需要入队等待
bitfields
final Node p = node.predecessor()
将对象头的锁记录指针指向lock record,升级为轻量级锁
成员变量赋值
新建一个工作线程
将头结点的ws设置为-1
当前线程栈中分配锁记录
Thread id
偏向锁状态
return
!isFulfilling(h.mode)
队列满了,执行下面逻辑
SynchronousQueue
CyclicBarrier cyclicBarrier = new CyclicBarrier(3)
默认是TransferStack.transfer()
o.notifyAll()
阻塞线程3
o.wait(timeout)
queue.put(\"121221\")
头结点是的状态为1或0
thread3
释放锁,唤醒阻塞的线程,开启新的一轮锁竞争
将head节点的waitStatus值设置为0
获取前置节点
o.wait()
线程状态
开始偏向锁撤销(等到竞争出现才释放锁的机制)
升级为重量级锁
LockSupport.park()
acquire(1)
(remaining = available - acquires)>0
轻量级锁00(标志位)
exclusiveOwnerThread=null
否 return false
唤醒线程2,线程2出队
Node s = node.nextLockSupport.unpark(s.thread)
unparkSuccessor(h)
暂停线程1
firstWaiter
r = tryAcquireShared(arg)
semaphore.acquire()
重新设置头结点
开启轻量级解锁
LockSupport.park(thread1)
hash
status=0
CAS成功
compareAndIncrementWorkerCount(c)
工作线程开始执行任务
标志位(2bit)
把status+1
node1waitStatus=0pre=node0thread=线程2next=node2
没有线程排队,进行CAS抢占锁
检查thread id是否为线程1
自旋到一定次数park线程
lock.newCondition().signalAll()
node1waitStatus=0pre=node0thread=线程2next=null
p == head
收藏
收藏
0 条评论
下一页