我试图了解如何在锁实现中使用fetch和add(原子操作)。
我在维基百科上看到这篇文章,我发现它至少在另一个地方重复了。实现没有意义,并期待我有一个或更多的错误。当然,我可能会错过一个微妙的观点而不是真正理解所描述的内容。
来自https://en.wikipedia.org/wiki/Fetch-and-add
<< atomic >>
function FetchAndAdd(address location, int inc) {
int value := *location
*location := value + inc
return value
}
record locktype {
int ticketnumber
int turn
}
procedure LockInit( locktype* lock ) {
lock.ticketnumber := 0
lock.turn := 0
}
procedure Lock( locktype* lock ) {
int myturn := FetchAndIncrement( &lock.ticketnumber ) //must be atomic, since many threads might ask for a lock at the same time
while lock.turn ≠ myturn
skip // spin until lock is acquired
}
procedure UnLock( locktype* lock ) {
FetchAndIncrement( &lock.turn ) //this need not be atomic, since only the possessor of the lock will execute this
}
根据文章他们首先做LockInit。 FetchAndIncrement调用FetchAndAdd并将inc设置为1。
如果这不包含错误,我不明白它是如何工作的。
访问它的第一个线程将获得它:
lock.ticketnumber = 1 lock.turn = 0。
假设在锁定发布之前还有5次锁定访问。
lock.ticketnumber = 6 lock.turn = 0
第一个线程释放锁。
lock.ticketnumber = 6 lock.turn = 1
下一个帖子进来,状态为
lock.ticketnumber = 7 lock.turn = 1
返回值:myturn = 6(faa之前的lock.ticketnumber)。
在这种情况下:
while lock.turn≠myturn
永远不会是真的。
此插图中是否有错误或我遗失了什么?
如果此实现中存在错误,可以修复它吗?
感谢名单
儒略
答案 0 :(得分:0)
当一个线程调用Lock时,它会旋转等待它返回的值,出于某种原因,我认为它一直在调用该函数。
当它旋转时,它等待直到另一个线程增加转动并最终成为myturn的数量。
抱歉浪费你的时间。