ReentrantLockソースベースワークフローの理解
25180 ワード
ReentrantLockとsynchronizedはjdk 1にある.8バージョン以降のパフォーマンスはほぼ同じで、synchronizedは優れていますが、synchronizedは割り込みとタイムアウトをサポートしていません.つまり、synchronizedによってブロックされると、リソースを取得できないままブロックされ、中断しても役に立たないため、同時システムのパフォーマンスに大きな影響を与えます.ロックは割り込みとタイムアウトをサポートし、試行メカニズムのロック取得もサポートし、synchronizedをよく拡張しているので、柔軟性からlockはsynchronizedより明らかに優れている.
きほんほうしき
錠をかける
リリースロック
きほんほうしき
//
// boolean fair
ReentrantLock(boolean fair)
// ,
void lock();
//
void unlock();
//
void lockInterruptibly() throws InterruptedException;
// ,
boolean tryLock();
// , timeout
boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException;
フラットロック
錠をかける
final void lock() {
acquire(1);
}
public final void acquire(int arg) {
//
if (!tryAcquire(arg) &&
// addWaiter ( )
// acquireQueued , LockSupport.park(this)
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
//
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//
// hasQueuedPredecessors ( ) true: , false:
if (!hasQueuedPredecessors() &&
// CAS
compareAndSetState(0, acquires)) {
//
setExclusiveOwnerThread(current);
return true;
}
}
//
//
else if (current == getExclusiveOwnerThread()) {
// c + 1 ( )
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc); //
return true;
}
return false;
}
//
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
//
if (pred != null) {
//
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//
enq(node);
return node;
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
//
for (;;) {
// prev
final Node p = node.predecessor();
// prev
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// park
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt()) // LockSupport.park(this);
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
リリースロック
public final boolean release(int arg) {
//
if (tryRelease(arg)) {
Node h = head;
// head unpark
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
// - 1
int c = getState() - releases;
//
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// c == 0
if (c == 0) {
free = true;
//
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
ノンフェアロック
final void lock() {
// ( )
if (compareAndSetState(0, 1))
//
setExclusiveOwnerThread(Thread.currentThread());
else
//
acquire(1);
}
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)) {
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;
}