// SubFetch(x,y) = atomically x-=y and return x (__sync_sub_and_fetch)
// AddFetch(x,y) = atomically x+=y and return x (__sync_add_and_fetch)
// CompareWait(x, y) = futex(&x, FUTEX_WAIT, y) wait on x if x == y
// Wake(x, y) = futex(&x, FUTEX_WAKE, y) wake up y waiters
struct Lock
{
Lock() : x(1) {}
void lock()
{
while (true)
{
if (SubFetch(x, 1) == 0)
return;
x = -1;
CompareWait(x, -1);
}
}
void unlock()
{
if (AddFetch(x, 1) == 1)
return;
x = 1;
Wake(x, 1);
}
private:
int x;
};
Linux 3.0提供了一個名爲futex的系統調用,在此係統調用上,很多併發實用程序都基於最近的pthread_mutex實現。無論何時編寫代碼,您都應該考慮是否使用現有的實現或自己編寫代碼是您項目的更好選擇。Linux 3.0:futex-lock死鎖錯誤?
以上是基於futex的一個鎖(互斥,1個許可證計數信號)的實現和在man futex(7)
它似乎包含死鎖錯誤,由此後多個線程試圖鎖定和解鎖它的語義描述幾千次,線程可以進入x == -1狀態,並且所有線程都卡在CompareWait中,但是沒有人持有該鎖。
任何人都可以看到錯誤在哪裏?
更新:我有點驚訝futex(7)/語義是如此的破碎。我完全重寫了Lock,如下所示...現在是否正確?
// CompareAssign(x,y,z) atomically: if (x == y) {x = z; ret true; } else ret false;
struct Lock
{
Lock() : x(0) {}
void lock()
{
while (!CompareAssign(x, 0, 1))
if (x == 2 || CompareAssign(x, 1, 2))
CompareWait(x, 2);
}
void unlock()
{
if (SubFetch(x, 1) == 0)
return;
x = 0;
Wake(x, 1);
}
private:
int x;
};
這裏的想法是,x具有以下三種狀態:
0: unlocked
1: locked & no waiters
2: locked & waiters
我聽說futexes看起來很簡單,很難正確使用它們。你有這樣的理由嗎? – 2012-03-08 16:43:13
見第1款 – 2012-03-08 16:44:04
呵呵? pthread_mutex有什麼問題? – 2012-03-08 16:46:11