[英]What is the deal with modifying the volatile boolean field of an object, while holding the specific monitor, when lazy locking?
我實現了一個惰性鎖定列表,該列表支持以下方法:布爾值add(T項),布爾值remove(T項),布爾值contains(T項)。
例如,add方法:
@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(); }
}
}
如果Node對象具有一個“標記”為易失性布爾字段,則默認情況下設置為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;
}
}
去掉:
@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(); }
}
}
在您的情況下, marked
是包含方法而不是添加方法必需的。 我的猜測是,添加功能中marked
-check的絕對不起作用。
marked
字段絕對必須是易變的,因為JIT保留重新排序代碼的權利(如果這樣做會帶來好處)。 唯一的保證是,在更改易失性字段之前,任何對易失性字段進行任何操作之前的代碼都已完全執行(發生在關系之前)。
因此,在上面的代碼中,如果字段不是可變的,則JIT可以決定在調用“包含”的線程中創建marked
的線程本地副本,然后再檢查該marked
本地版本,但是該版本可能已過時那一點。 在這種情況下,同時運行contains
和remove
可能會導致競爭狀況。
作為附帶說明,應該提到Concurrent包中的Collections解決所有這些問題的方式更加優雅(並且沒有bug),因此,在所有情況下均應優先考慮。 如果復制標准庫中已經存在的類,則通常會更糟地實現它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.