lock()
//获取锁,一直等待锁可用
public void lock()
{
sync.lock();
}
//公平锁获取
final void lock()
{
acquire(1);
}
//非公平锁的获取
final void lock()
{
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
FairSync.tryAcquire
函数的执行流程:
(1)如果当前锁状态state
为0,说明锁处于闲置状态可以被获取。首先调用hasQueuedPredecessors判断当前线程是否还有前驱节点在等待获取锁。如果没有,直接返回false;没有的情况下,通过调用compareAndSetState(CAS)修改state值来标记自己已经拿到锁,CAS执行成功后调用setExclusiveOwnerThread设置锁的持有者为当前线程。程序执行到现在说明锁获取成功,返回true;
(2)如果当前锁状态state不为0,但当前线程已经持有锁(current == getExclusiveOwnerThread()),由于锁是可重入(多次获取)的,则更新重入后的锁状态state += acquires 。锁获取成功返回true。
protected final boolean tryAcquire(int acquires)
{
final Thread current = Thread.currentThread();
//获取锁状态
int c = getState();
if (c == 0)
{
if (!hasQueuedPredecessors() && //判断当前线程是否还有前节点
compareAndSetState(0, acquires)) //CAS方法修改state
{
//获取锁成功,设置锁的持有线程为当前线程
setExclusiveOwnerThread(current);
return true;
}
}
// 已经持有锁
else if (current == getExclusiveOwnerThread())
{
//重入
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
//更新state的状态
setState(nextc);
return true;
}
return false;
}
NonFairSync.tryAcquire
protected final boolean tryAcquire(int acquires)
{
return nonfairTryAcquire(acquires);
}
final boolean nonfairTryAcquire(int acquires)
{
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0)
{
if (compareAndSetState(0, acquires)) //CAS修改state
{
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread())
{
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
Note: 通过对比公平锁和非公平锁tryAcquire的代码可以看到,非公平锁的获取略去了!hasQueuedPredecessors()这一操作,也就是说它不会判断当前线程是否还有前节点(prev node)在等待获取锁,而是直接去进行锁获取操作。
unlock
//释放锁
public void unlock()
{
sync.release(1);
}
tryRelease
protected final boolean tryRelease(int releases)
{
// 计算释放后的state的值
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0)
{
//锁全部释放,可以唤醒下一个等待线程
free = true;
//设置锁持有线程为null
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
Note: tryRelease用于释放给定量的资源。在ReetrantLock中每次释放量为1,也就是说,在可重入锁中,获取锁的次数必须要等于释放锁的次数,这样才算是真正释放了锁。在锁全部释放后(state==0)才可以唤醒下一个等待线程。
等待条件Condition
Condition接口和AQS对Condition接口的实现
synchronized和ReentrantLock的选择
ReentrantLock在加锁和内存上提供的语义与内置锁synchronized相同,此外它还提供了一些其他功能,包括定时的锁等待、可中断的锁等待、公平性,以及实现非块结构的加锁。从性能方面来说,在JDK5的早期版本中,ReentrantLock的性能远远好于synchronized,但是从JDK6开始,JDK在synchronized上做了大量优化,使得两者的性能差距不大。synchronized的优点就是简洁。 所以说,两者之间的选择还是要看具体的需求,ReentrantLock可以作为一种高级工具,当需要一些高级功能时可以使用它。