1、睡眠,挂起,中断,阻塞区别:
阻塞:被动,缺少一些资源
中断:只是设置了一个标识,可以继续执行,设置了中断后,再执行sleep,wait,join时会抛出一个interruptedException,且中断标识 被清除。
睡眠:自己主动停止执行,放弃cpu资源,但是不会释放对象锁。
挂起:自己主动停止执行。
2、AQS
AbstractQueuedSynchronizer,同步器, JUC中很多类的实现依赖AQS。
里面会有一个等待队列,帮助实现获取锁操作。
3、Sycn
Sync实现AQS,有以下两个子类
FairSync:获取锁时,需要判断是不是有前驱节点
NonfairSync:不用判断是否有前驱节点。
公平锁和非公平锁,只在获取锁的时候有区别。公平锁,节点直接进入CHL队列;非公平锁先获取锁,如果获取失败进入CHL队列,之后的操作和公平锁是一样的了。
4、CHL队列(SyncQueue)
锁等待队列,没有获得锁的线程,都会生成对应的node,放入该队列中,遵循FIFO原则;
node中的状态waitStatus:负数时,表示没有获取锁;0时新生节点,需要根据后面节点状态设置节点;正数时,表示已经获得锁/超时/线程被中断,不应该在CHL队列中。
1)SIGNAL = -1: 节点的继任节点是(或者将要成为)BLOCKED状态(例如通过LockSupport.park()操作),因此一个节点一旦被释放(解锁)或者取消就需要唤醒(LockSupport.unpack())它的继任节点。 2)CONDITION = -2:表明节点对应的线程因为不满足一个条件(Condition)而被阻塞。
3)0: 正常状态,新生的非CONDITION节点都是此状态。
4)CANCELLED = 1: 节点操作因为超时或者对应的线程被interrupt。节点不应该留在此状态,一旦达到此状态将从CHL队列中踢出。
5)非负值标识节点不需要被通知(唤醒)。
5、条件队列(ConditionObject)
实现类ConditionObject在AQS中,底层使用LockSupport.park(实现)
await:生成Node添加入Condition的waiter链表中,释放锁,并自旋等待锁。
signal:获取waiter链表中的第一个node,出队列,unpark。
SyncQueue,ConditionQueue关系:想要获得锁需要进入SyncQueue;增加条件的话会进入ConditionQueue,满足条件后从ConditionQueue退出,但是没有获得锁, 想要获得锁还得进入SyncQueue。