手写ReentrantLock
最近学习了Java语言中锁相关知识,看了一下ReentrantLock
源码,自己手写了一个ReentrantLock
。
ReentrantLock
是一个可重入锁,并且在源码中通过构造函数可以使其在公平锁和非公平锁之间转换。
可重入锁即当前线程可以在不释放锁的情况下多次获取锁,但是释放锁的次数应与获取锁的次数相同,否则会抛出IllegalMonitorStateException
异常。
公平锁和非公平锁的区别在与,公平锁使先进入等待队列的线程先获取锁,每个线程都有机会获取锁。非公平锁则是每个线程获取锁的几率不确定,非公平锁并发性较好,但容易造成某些线程长时间获取不到锁。
不可重入ReentrantLock,非公平
/**
* 不可重入锁
*/
public class WonderReentranrLock{
//标记获取锁的线程,原子类型的引用保证原子性
private AtomicReference<Thread> owner = new AtomicReference<>();
//抢锁失败时进入等待队列
private Queue<Thread> waitQueue = new LinkedBlockingQueue();
/**
* 加锁
*/
public void lock(){
//抢锁失败
if(!tryLock()){
Thread current = Thread.currentThread();
//线程进入等待队列
waitQueue.offer(current);
//继续尝试抢锁
for(;;){
//获取队列头部
Thread head = waitQueue.peek();
//如果当前线程在队列头部
if(current == head){
//抢锁
if(!tryLock()){
//如果抢锁失败
LockSupport.park();
}else{
//如果抢锁成功,线程出队列
waitQueue.poll();
return;
}
}else{
//如果不在队列头部,将线程挂起
LockSupport.park();
}
}
}
//成功则抢到了锁
}
/**
* 尝试加锁
* @return
*/
public boolean tryLock(){
Thread current = Thread.currentThread