Java concurrencyの公平ロック動力ノードJava学院の整理
3935 ワード
公平ロック(JDK 1.7.0_に基づく。40)
1.ロック()
unlock()はReentrant Lock.javaで実現されたソースコードは以下の通りです。
アンロック()はAQSのrelease()関数によって実現されるアンロック関数です。
ここでは、「1」という意味は、「ロックを解除した状態」を設定するパラメータです。「公平ロック」は重入可能なので、同じスレッドに対してはロックを1回解除するごとにロック状態-1となります。
AQSについては、Reentrant Lockとsyncの関係は以下の通りである。
2.リリース()
release()はAQSで実現されました。ソースは以下の通りです。
release()は、先にtryRelease()を呼び出して、現在のスレッドロックが持つロックを解除してみます。成功すると、後続のスレッドを起動してtrueに戻ります。そうでなければ、直接falseに戻ります。
3.tryRelease()
tryRelease()はReentrant Lock.javaのSync類で実現され、ソースは以下の通りです。
tryRelease()はロックを解除する試みです。
(01)「現在のスレッド」が「鍵の所有者」でない場合、異常を投げかける。
(02)「現在のスレッド」が今回のリリースロック操作後にロックの所有状態が0(つまり、現在のスレッドはこの「ロック」を完全に解放する)である場合、「ロック」の持ち主はnullであり、つまりロックは取得可能状態である。また、現在のスレッドのロックを更新した状態は0です。
get State()、set State()は前の章で紹介しましたが、ここでは説明しません。
get Exclusive Ownerantread()、set Exclusive Ownerantread()はAQSの親クラスAbstractOwnable Syncronizer.javaで定義されています。ソースは以下の通りです。
release()において「現在スレッド」がロック解除に成功すると、現在のスレッドの後継スレッドが呼び覚まされます。
CLHキューのFIFOルールによれば、「現在スレッド」(すなわちロックを取得したスレッド)は、必ずヘッドである。CLH列が空でないと、ロックの次の待ちスレッドが起動されます。
次にunparkSuccess orのソースコードを見てみます。これはAQSで実現されます。
unparkSuccess orの役割は「現在のスレッドの後継スレッドを呼び覚ます」というものです。後続スレッドが呼び覚まされると、このロックを取得して運転を再開することができます。
node.waitStatusの説明については、「前の章でNode類についての紹介」を参照してください。
締め括りをつける
「解除錠」のプロセスは、「鍵を取得する」プロセスに対して比較的簡単である。ロックを解除する時、主に行われる操作は、現在のスレッドに対応するロックを更新した状態です。現在のスレッドのロックが完全に解除されている場合、「ロック」を持つスレッドはnullとなり、現在のスレッドの状態を空にして、後続のスレッドを起動します。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。
1.ロック()
unlock()はReentrant Lock.javaで実現されたソースコードは以下の通りです。
public void unlock() {
sync.release(1);
}
説明:アンロック()はAQSのrelease()関数によって実現されるアンロック関数です。
ここでは、「1」という意味は、「ロックを解除した状態」を設定するパラメータです。「公平ロック」は重入可能なので、同じスレッドに対してはロックを1回解除するごとにロック状態-1となります。
AQSについては、Reentrant Lockとsyncの関係は以下の通りである。
public class ReentrantLock implements Lock, java.io.Serializable {
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer {
...
}
...
}
そこから、私たちはsyncがRentrant Lock.javaのメンバーオブジェクトであり、SyncはAQSのサブクラスであることを発見しました。 2.リリース()
release()はAQSで実現されました。ソースは以下の通りです。
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
説明:release()は、先にtryRelease()を呼び出して、現在のスレッドロックが持つロックを解除してみます。成功すると、後続のスレッドを起動してtrueに戻ります。そうでなければ、直接falseに戻ります。
3.tryRelease()
tryRelease()はReentrant Lock.javaのSync類で実現され、ソースは以下の通りです。
protected final boolean tryRelease(int releases) {
// c
int c = getState() - releases;
// “ ” “ ”, !
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// “ ” , “ ” null, 。
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
// 。
setState(c);
return free;
}
説明:tryRelease()はロックを解除する試みです。
(01)「現在のスレッド」が「鍵の所有者」でない場合、異常を投げかける。
(02)「現在のスレッド」が今回のリリースロック操作後にロックの所有状態が0(つまり、現在のスレッドはこの「ロック」を完全に解放する)である場合、「ロック」の持ち主はnullであり、つまりロックは取得可能状態である。また、現在のスレッドのロックを更新した状態は0です。
get State()、set State()は前の章で紹介しましたが、ここでは説明しません。
get Exclusive Ownerantread()、set Exclusive Ownerantread()はAQSの親クラスAbstractOwnable Syncronizer.javaで定義されています。ソースは以下の通りです。
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
// “ ”
private transient Thread exclusiveOwnerThread;
// “ ” t
protected final void setExclusiveOwnerThread(Thread t) {
exclusiveOwnerThread = t;
}
// “ ”
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
...
}
4.unparkSuccess or()release()において「現在スレッド」がロック解除に成功すると、現在のスレッドの後継スレッドが呼び覚まされます。
CLHキューのFIFOルールによれば、「現在スレッド」(すなわちロックを取得したスレッド)は、必ずヘッドである。CLH列が空でないと、ロックの次の待ちスレッドが起動されます。
次にunparkSuccess orのソースコードを見てみます。これはAQSで実現されます。
private void unparkSuccessor(Node node) {
//
int ws = node.waitStatus;
// <0, =0
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
// “ ”, , for 。
// , “ <=0”
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
// “ ”
if (s != null)
LockSupport.unpark(s.thread);
}
説明:unparkSuccess orの役割は「現在のスレッドの後継スレッドを呼び覚ます」というものです。後続スレッドが呼び覚まされると、このロックを取得して運転を再開することができます。
node.waitStatusの説明については、「前の章でNode類についての紹介」を参照してください。
締め括りをつける
「解除錠」のプロセスは、「鍵を取得する」プロセスに対して比較的簡単である。ロックを解除する時、主に行われる操作は、現在のスレッドに対応するロックを更新した状態です。現在のスレッドのロックが完全に解除されている場合、「ロック」を持つスレッドはnullとなり、現在のスレッドの状態を空にして、後続のスレッドを起動します。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。