我不知道我是否很好地理解你的问题,正如你所说,当你锁定一个子树进行写入时,整个结构被锁定。 因此,简单的解决方案是为整个结构设置一个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