我想在我的一个应用程序中用C ++实现排队锁定。 我正在通过以下论文中的算法: http://www.google.co.in/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCUQFjAA&url=http%3A%2F%2Fwww.cs.rice.edu%2F~johnmc%2Fpapers%2Ftocs91.pdf&ei=HpRfUKCZFsfWrQfpgIGACQ&usg=AFQjCNF_QamPWhJrq5dSjJjFjO7W3WzJ5Q&sig2=3TU1vo_aAYbM2fmLxeiZ0A
type qnode = record
next : ^qnode
locked : Boolean
type lock = ^qnode
// parameter I, below, points to a qnode record allocated
// (in an enclosing scope) in shared memory locally-accessible
// to the invoking processor
procedure acquire_lock (L : ^lock, I : ^qnode)
I->next := nil
predecessor : ^qnode := fetch_and_store (L, I)
if predecessor != nil // queue was non-empty
I->locked := true
predecessor->next := I ---A
repeat while I->locked // spin ---C
procedure release_lock (L : ^lock, I: ^qnode)
if I->next = nil // no known successor
if compare_and_swap (L, I, nil) // compare_and_swap returns true iff it swapped
return
repeat while I->next = nil // spin --B
I->next->locked := false ---D
A& B正在访问相同的变量(前一个 - >下一个& I->下一个)以及C& D(锁定变量)但在访问之前它们没有被锁定。我在这里错过了什么吗?
答案 0 :(得分:1)
这些并发访问确实可以竞争,但算法的设计是容忍的。
B处的旋转实际上是为了防止与A的比赛。在D,我们需要I->next
为非零。 I->next
(此处称为predecessor->next
)被A设置为非零。正如您所注意到的,这可能会竞争,因此在B处有一个旋转循环以等待另一个线程设置{{ 1}}有效的东西。
让我们来看看C& D. I->next
线是锁的实际“旋转”部分;如果尝试获取锁的线程必须等待另一个线程释放它,它会在此循环中旋转。如果释放锁的线程在获取线程到达repeat while I->locked
之前将I->next->locked
设置为false
,则循环将永远不会启动。