tryAcquire()、addWaiter()、acquire Qued()を詳細に説明する。
3512 ワード
本論文の例ではtryAcquire()、addWaiter()、acquire Qued()の使い方を共有しています。参考にしてください。具体的な内容は以下の通りです。
tryAcquire()
addWaiter()
先に待ち行列のtailノードpredを見つけます。predなら!=nullは、現在スレッドをpredの後に追加して待ち行列に入ります。もしtailノードが存在しないなら、enq()を実行します。
ノードを挿入した後、acquire Queuedを呼び出してブロックします。
acquire Queued()
以上は小编が绍介したtryAcquire()、addWaiter()、acquire Queued()の使い方を详しく整理していますので、皆さんに助けてほしいです。もし何かご质问があれば、メッセージをください。ここでも私たちのサイトを応援してくれてありがとうございます。
tryAcquire()
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;
}
まず、stateが0かどうかを判断し、0であれば上記のロック方法の前半部分を実行し、CAS操作によってstateの値を0から1に変更します。そうでなければ、現在のスレッドがexclusive Owner Threadかどうかを判断し、state+、つまり再入力ロックの体現を行います。前半部分はCASによって同期を保証しています。後半部分は同期されていません。後半部分はスレッド再入で、再びロックを獲得した時にトリガされる操作で、現在のスレッドはロックされているので、Rentrant Lockの属性操作にロックは不要です。tryAcquire()の取得に失敗した場合、addWaiter()を実行して待ち行列に独占モードを追加するノード。addWaiter()
/**
* Creates and enqueues node for current thread and given mode.
*
* @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
* @return the new node
*/
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;
}
この方法のコメント:現在スレッドを作成します。ノード・EXCLUSIVEは独占ロックです。ノード・SHAREDは共有ロックです。先に待ち行列のtailノードpredを見つけます。predなら!=nullは、現在スレッドをpredの後に追加して待ち行列に入ります。もしtailノードが存在しないなら、enq()を実行します。
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
ここでループを行いましたが、この時点でtailが存在すると、同じステップの追加チームの最後の動作が実行されます。まだ存在しない場合は、現在のスレッドをhead結点とします。ノードを挿入した後、acquire Queuedを呼び出してブロックします。
acquire Queued()
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
先に現在のノードの前のノードpを取得し、pがheadであればもう一度tryAcquire(arg)操作を行い、成功すれば戻ります。そうでなければShuldParkAfterFaileAcquire、parkAndCheckInterruptを実行してブロック効果を達成します。以上は小编が绍介したtryAcquire()、addWaiter()、acquire Queued()の使い方を详しく整理していますので、皆さんに助けてほしいです。もし何かご质问があれば、メッセージをください。ここでも私たちのサイトを応援してくれてありがとうございます。