1、java锁
隐式锁( synchronized, 他是基于jvm内置锁),加锁与解锁的过程不需要我们在代码当中人为的控制,jvm会自动去加锁跟解锁
显式锁 ReentrantLock, 一个可重入的锁整个加锁跟解锁过程需要我们手动编写代码去控制
2、AbstractQueuedSynchronizer源码
(1)ReentrantLock的构造方法
(2)是悲观锁
(3)公平锁FairSync
(4)可重入锁(讲解AQS)
可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。ReentrantLock 和 synchronized 不一样,需要手动释放锁,所以使用 ReentrantLock的时候一定要手动释放锁,并且加锁次数和释放次数要一样,否则其他线程会一直等待
解锁的时候state会减1,execlusiveOwnerThread为null的时候代表解锁完毕且state为0
多线程的情况:
图解多线程的情况:
由于线程1已经加锁,state=1,线程2加锁失败需要进行排队,只能够等到线程1执行完毕释放锁,state=0且exclusive OwnerThread=null的时候会唤醒等待的线程2
公平锁具有先来先排队,且先来的具有获取锁的优先权的特点
(5)CLH队列(双向链表)
CLH队列是Craig、Landin. Hagersten 三人发明的一种基于双向链表数据结构的队列 。Java中的CLH队列是原CLH队列的一个变种,线程由原自旋机制改为阻塞机制
移除节点的操作:
增加结点的操作:
线程的状态:
条件队列:
在put函数中已经有获取锁的操作,在执行await函数的时候是需要释放锁的。
条件队列队满的处理方式:
(6)非公平锁