重入锁ReentrantLock
what:
支持可重入的锁,并且支持获取锁时的公平和非公平性选择.
why:
不支持重进入的锁,没有考虑当前占有锁的线程再次获取锁的场景,tryAcquire第一次是true第二次就是false.
how:
1.线程再次获取锁.
锁需要识别获取锁的线程是否为当前占有的线程,如果是,再次获取成功.
2.锁的最终释放.
线程重复n次获取了锁,随后在第n次释放该锁后,其他线程能够获取到该锁.锁的最终释放要求锁对于获取进行计数自增,计数表示当前锁被重复获取的次数,而锁被释放时,计数自减,当计数等于0时表示锁已经成功释放.
具体实现nonfairTryAcquire方法
final boolean nonfairTryAcquire(int acquires){
//获取当前线程
final Thread current = Thread.currentThread();
//当前获取锁状态
int c = getState();
//如果未获取锁
if(c == 0){
if(compareAndSetState(0,acquires)){//尝试获取锁
//将线程设置为当前占有锁线程
setExclusiveOwnerThread(current);
return true;
}
}else if(current == getExclusiveOwnerThread()){ //如果该线程为当前占有线程
int nextc = c + acquires; //同步状态进行增加
if(nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;//返回true表示获取同步状态成功
}
return false;
}
释放具体实现tryRelease方法
protected final boolean tryRelease(int releases){
int c = getState()-releases;
if(Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if(c == 0){//同步状态为0,全部已经释放
free = true; //设置状态为free
setExclusiveOwnerThread(null); //当前占有线程为空
}
setState(c);
return free;
}
公平锁
what:
绝对时间上,先对锁获取的请求一定先满足,这个锁就是公平的.锁获取的顺序一定是FIFO的
how:
ReentrantLock的tryAcquire方法
protected final boolean tryAcquire(int acquires){
final Thread current = Thread.currentThread();
int c = getState();
if(c == 0){
//与非公平方式获取锁的主要区别是,要判断是否有前驱节点,没有才能获取成功
if(!hasQueuedProdeccessor() && compareAndSetState(0,acquires)){
setExclusiveOwnerThread(current);
return true;
}
}else if(current == getExclusiveOwnerThread()){
int nextc = c + acquires;
if(nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}