转载请注明出处:http://blog.csdn.net/linxdcn/article/details/72850375
在ReetrantLock内部基于AQS类实现了一个抽象类Sync同步器,对于AQS不熟悉的,可以看看这篇文章:AbstractQueuedSynchronizer同步器。基于Sync还实现了公平锁和非公平锁:
//抽象同步器Sync继承AQS,子类可以非公平或者公平锁
abstract static class Sync extends AbstractQueuedSynchronizer {
abstract void lock();
// 非公平锁的尝试获取
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 跟公平锁获取的区别时,这里少了判断队列是否为空的函数hasQueuedPredecessors
// 即不管排队队列是否为空,该线程都将直接尝试获取锁
if (compareAndSetState(0, acquires)) {
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;
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
}
//非公平锁的同步器
static final class NonfairSync extends Sync {
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
// 公平锁的同步器
static final class FairSync extends Sync {
final void lock() {
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
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;
}
}
ReentrantLock的方法源码比较简单,主要是委托给Sync同步器实现。
//构造函数,默认使用非公平锁同步器
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
public void lock() {
sync.lock();
}
public void unlock() {
sync.release(1);
}
// 实现了条件变量
public Condition newCondition() {
return sync.newCondition();
}
条件变量是实现了Java中的Condition接口的类,其中Condition中的await、signal、signalAll方法与Object中的wait、notify、notifyAll类似。
假设现在我们有三个线程A、B、C,申请了一个ReetrantLock,以及两个条件变量,如下代码,下面举例说明Condition如何工作
Lock lock = new ReentrantLock();
Condition conditionX = lock.newCondition();
Condition conditionY = lock.newCondition();
假设已经有一个线程获取的了lock,然后线程A、B、C依次获取lock,状态图如下:
线程A、B分别调用了conditionX.await()
,源码如下
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
// 把等待线程包装为Node
Node node = addConditionWaiter();
// 释放锁
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
// 线程在此挂起
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
// 当收到signal通知后,线程会继续,抢占锁
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
// 如果抢占不成功,线程继续挂起
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
//在等待队列中新建一个Node
private Node addConditionWaiter() {
Node t = lastWaiter;
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
线程A、B均在函数LockSupport.park(this)
处被挂起,等待通知,目前的状态图如下:
线程C获得锁,执行。当C执行完后,调用signal
通知await
的线程
// 将一个等待时间最长的waitQueue的Node移到lockQueue
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
final boolean transferForSignal(Node node) {
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
Node p = enq(node);
int ws = p.waitStatus;
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
(1)synchronized关键字无法中断一个正在等候获得锁的线程,也无法通过轮询得到锁;ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义,但是添加了类似轮询锁、定时锁等候和可中断锁等候的一些特性。
(2)根类 Object 包含某些特殊的方法,用来在线程的 wait() 、 notify() 和 notifyAll() 之间进行通信;Lock 框架包含了对 wait 和 notify 的概括,这个概括叫作 条件(Condition),对于指定的 Lock ,可以有不止一个条件变量与它关联。
(3)synchronized的优点:使用 synchronized 的时候,不可能忘记释放锁;在退出 synchronized 块时,JVM 会做这件事;当 JVM 用 synchronized 管理锁定请求和释放时,JVM 在生成线程转储时能够包括锁定信息。这些对调试非常有价值,因为它们能标识死锁或者其他异常行为的来源
(4)java.util.concurrent.lock 中的锁定类是用于高级用户和高级情况的工具 。一般来说,除非您对 Lock 的某个高级特性有明确的需要,或者有明确的证据(而不是仅仅是怀疑)表明在特定情况下,同步已经成为可伸缩性的瓶颈,否则还是应当继续使用 synchronized。
https://www.ibm.com/developerworks/cn/java/j-jtp10264/index.html
转载请注明出处:http://blog.csdn.net/linxdcn/article/details/72850375