boolean add(T item)、boolean remove(T item)、boolean contains(T item)のようなメソッドをサポートする遅延ロックリストを実装しました。遅延ロック時に特定のモニタを保持しながら、オブジェクトの揮発性のブール値フィールドを変更することは何ですか?
例えばaddメソッドは:
Nodeオブジェクトは、揮発性のブールフィールドを持つ@Override
public boolean add(T item) {
int key = item.hashCode();
while(true){
Node pred = head;
Node curr = pred.next;
while(curr.key < key) { pred = curr; curr = curr.next; }
pred.Lock.lock();
curr.Lock.lock();
try{
if(!pred.marked && !curr.marked && pred.next == curr){
if(curr.key == key){ return false; }
else{ Node insertMe = new Node(item); insertMe.next = curr; pred.next = insertMe; return true; }
}
} finally{ pred.Lock.unlock(); curr.Lock.unlock(); }
}
}
デフォルトでfalseに設定し、「マーク」。ノードのロックはリエントラントなものです。 trueとマークされたノードは、すでにremoveメソッドによって削除されているとみなされます。しかし、特定のオブジェクトのモニタが特定のスレッドによって保持されている場合、これはなぜ関連していますか?言い換えれば、スレッドがオブジェクトのロックを取得していて、そのノードが削除済みとしてマークされていることをいつでも知ることができますか?
編集: containsメソッドは明らかにロックされませんが、containsチェックを行うために削除されたノードをマークする目的はありますか?したがって、マークされたフィールドをvolatile宣言する必要がありますか?
は含まれています
@Override
public boolean contains(T item) {
int key = item.hashCode();
while(true){
Node curr = head;
while(curr.key < key) { curr = curr.next; }
if(curr.key == key && !curr.marked) return true;
else return false;
}
}
削除:addメソッドのためのメソッドが含まれていないために、あなたの場合は
@Override
public boolean remove(T item) {
int key = item.hashCode();
while(true){
Node pred = head;
Node curr = pred.next;
while(curr.key < key) { pred = curr; curr = curr.next; }
pred.Lock.lock();
curr.Lock.lock();
try{
if(!pred.marked && !curr.marked && pred.next == curr){
if(curr.key != key) { return false; }
else{
curr.marked = true;
pred.next = curr.next;
return true;
}
}
} finally{ pred.Lock.unlock(); curr.Lock.unlock(); }
}
}
すべてのことは、練習と並行処理の理解のためのものです。マークされた説明は正当だと思われますが、追加については確かですか?たとえば、スレッドt1がリストを反復する場合、この追加t1スレッドがpredとcurrの両方をロックする前に、ローカルpredとcurrが参照を持つようになりました。t2は、t1のpredがまだ参照を保持しているノードを削除しました。 predが現在マークされていない場合、t1のpredで参照されるノードはすでに削除されていますが、curr.key ==キーをチェックして正しいとみなしませんか? – Greg
それは正しいです。しかし、マルチスレッドでは、 'contains'のリクエストは、あなたが答えを受け取った瞬間、常に古くなっています。しかし、それはスレッドの問題を引き起こさないので、間違っているわけではありません。 – TwoThe
メソッドがロックを取得する前にノード*に反復しているので、 'add'メソッドの' marked'チェックが必要です。この時点で同時に実行されている 'remove'操作が完了しなかった可能性があります。その場合、 'add'はロックされた時点までに削除されたノードへの参照を保持します。これは非常にまれなケースであるため、コードは操作全体のロックを解除して繰り返すことでこれを解決します。 – Holger