三、源码篇
终于可以看源码了,这个还是大家自己个儿看吧。推荐的解读顺序是:
- 锁实现 与 管理阻塞线程(独占锁:ReentrantLock)
- 线程等待await / 通知signal(ReentrantLock中 newCondition())
- 独占锁和共享锁(共享锁:CountDownLatch、ReentrantReadWriteLock)
- 线程中断interrupt(1和2过程中的中断处理)
- 案例 LinkedBlockingQueue
如果实在枯燥难看,下翻流程图部分,助你一臂之力。
类图
ReentrantLock类图流程图
lock()
lock()代码流程图unlock()
unlock()代码流程图condition.await()
condition.await()代码流程图condition.signal()
condition.signal()代码流程图看源码的可借鉴的地方,看源码学习、借鉴如何做设计?我觉得比较好的地方分享给大家。
锁
共享锁
锁的可重入性
写法方面
设计模式
推荐一篇文章 http://blog.csdn.net/fw0124/article/details/6672522
再读ReentrantLock源码
- 内部维持两个链表,阻塞链表、等待链表。
- await时,记录当前Thread的Node节点加入等待链表,暂存锁的重入值,release()释放锁,进入阻塞态,等待被唤醒,唤醒后,尝试走获锁流程。
- signal时,取出Node,移入阻塞链表,唤醒Node引用的Thread。
- 锁为啥要这样设计newCondition
await 会阻塞当前线程、记录lock重入的次数,所以必须在lock块内执行。
signal 根据node节点唤醒对应Thread,必须在获得锁的线程才能调用signal,signal会检测获取锁线程和 当前线程是否为一个线程,必须为一个线程,否则抛出异常,因为signal内部代码块无法保证事务,所以也必须在lock块内部。做了强制判断。
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
- 在BlockingQueue阻塞队列中,用了两个锁,putLock和takeLock,用了signal一个一个串行的唤醒,同时为了避免发生死锁。
网友评论