我不知道我是否很好地理解你的問題,正如你所說,當你鎖定一個子樹進行寫入時,整個結構被鎖定。 因此,簡單的解決方案是爲整個結構設置一個RW鎖。
順便說一句,java.util.concurrent.atomic
不會幫助你超過RW鎖的樹。
如果你希望能夠鎖定的兄弟姐妹independly,你可以與第二溶液(鎖的樹,其中每個節點有其父的引用)去。
鎖定一個節點將使用它的寫鎖來鎖定它,並使用讀鎖來鎖定每個父節點。 因爲您無法獲取其寫入鎖定,因此鎖定已獲取讀取鎖定的子項時,父級無法在子級鎖定。 只有在沒有其他線程已經寫入鎖定任何父項的情況下,才允許鎖定子項。
上述的鎖是獨佔鎖。 (對於讀 - 寫鎖的另一個名稱是共享的獨佔鎖)
要添加共享鎖,每個節點還需要的原子整數,指示: 如果它是正的,間接的寫鎖定兒童的數量;如果它是否爲節點已被讀鎖定的次數。 此外,節點及其父母將被讀取鎖定,以避免父母獲取新的寫鎖。
的僞代碼:
Node {
// fields
parent: Node
lock: RWLock
count: AtomicInteger
}
public boolean trylocktree(node: Node, exclusive: boolean) {
if (exclusive) {
return trylocktree_ex(node, true);
} else {
return trylocktree_sh(node);
}
}
private boolean switch_count(i: AtomicInteger, diff: int) {
// adds diff to i if the sign of i is the same as the sign of diff
while (true) {
int v = i.get();
if (diff > 0 ? v < 0 : v > 0)
return false;
if (i.compareAndSet(v, v + diff))
return true;
}
}
private boolean trylocktree_ex(node: Node, writing: boolean) {
// check if a node is read-locked
if (!switch_count(node.count, 1))
return false;
// lock using the lock type passed as an arg
if (!node.lock(writing).trylock()) {
node.count--;
return false;
}
// read-lock every parent
if (!trylocktree_ex(node.parent, false)) {
node.count--
node.lock(writing).unlock();
return false;
}
return true;
}
private boolean trylocktree_sh(node: Node) {
// mark as shared-locked subtree
if (!switch_count(node.count, -1))
return false;
// get shared-lock on parents
if (!readlock_recursively(node)) {
node.count++;
return false;
}
return true;
}
private boolean readlock_recursively(node: Node) {
if (!node.lock(false).trylock())
return false;
if (!readlock_recursively(node.parent)) {
node.lock(false).unlock();
return false;
}
return true;
}
如果任何鎖定,因此無法獲取,那麼你解開你已鎖定並稍後重試(你可以使用全局條件變量,超時等,以實現這個)。
編輯:添加代碼讀鎖定/寫鎖定樹
來源
2011-05-27 16:03:58
Kru
遠離「原子」,正確理解和實施是非常微妙的。 – toto2 2011-05-28 14:19:08
你的第二個解決方案似乎是正確的。當需要鎖定節點時,需要獲取全局鎖,以便可以檢查該節點的所有子節點都未鎖定,並且沒有鎖定其父節點。 – toto2 2011-05-28 14:32:45
順便說一下,Commons Transaction是[available](http://commons.apache.org/transaction/download_transaction.cgi),但我不知道它對你是否有用。 – toto2 2011-05-28 14:36:46