下面的代碼包含潛在的死鎖,但似乎是必要的:要將數據安全地從另一個容器複製到一個容器,必須鎖定兩個容器以防止在另一個線程中發生更改。獲取對兩個互斥鎖的鎖定並避免死鎖
void foo::copy(const foo & rhs)
{
pMutex->lock();
rhs.pMutex->lock();
// do copy
}
Foo有一個STL容器,「do copy」基本上由使用std :: copy組成。如何在不引入死鎖的情況下鎖定兩個互斥鎖?
下面的代碼包含潛在的死鎖,但似乎是必要的:要將數據安全地從另一個容器複製到一個容器,必須鎖定兩個容器以防止在另一個線程中發生更改。獲取對兩個互斥鎖的鎖定並避免死鎖
void foo::copy(const foo & rhs)
{
pMutex->lock();
rhs.pMutex->lock();
// do copy
}
Foo有一個STL容器,「do copy」基本上由使用std :: copy組成。如何在不引入死鎖的情況下鎖定兩個互斥鎖?
在foo
的實例上強加某種總訂單,並始終以遞增或遞減的順序獲取其鎖定,例如,foo1->lock()
,然後foo2->lock()
。
另一種方法是使用功能語義,而不是寫一個foo::clone
方法,該方法創建一個新的實例,而不是翻轉現有的實例。
如果您的代碼執行大量鎖定,則可能需要複雜的死鎖避免算法,如banker's algorithm。
這個怎麼樣?
void foo::copy(const foo & rhs)
{
scopedLock lock(rhs.pMutex); // release mutex in destructor
foo tmp(rhs);
swap(tmp); // no throw swap locked internally
}
這是異常安全的,而且線程安全。要100%線程保存,您需要查看所有代碼路徑,然後再次使用另一組眼睛重新查看,之後再次查看它...
爲了避免死鎖,它可能是最好的,等到這兩種資源都可以鎖定:
不知道該互斥您使用所以這裏API是一些任意的僞代碼,假設can_lock()
只有檢查它是否可以鎖定一個互斥體,而try_lock()
返回true,如果它沒有鎖,而假,如果互斥鎖已被其他人鎖定。
void foo::copy(const foo & rhs)
{
for(;;)
{
if(! pMutex->cany_lock() || ! rhs.pMutex->cany_lock())
{
// Depending on your environment call or dont call sleep()
continue;
}
if(! pMutex->try_lock())
continue;
if(! rhs.pMutex->try_lock())
{
pMutex->try_lock()
continue;
}
break;
}
// do copy
}
爲了避免死鎖,最好引入一個活鎖?並旋轉,使用100%的CPU? – bk1e 2010-02-13 05:17:40
您可以嘗試使用的scoped_lock或auto_lock同時鎖定兩個互斥....像銀行轉賬做...
void Transfer(Receiver recv, Sender send)
{
scoped_lock rlock(recv.mutex);
scoper_lock slock(send.mutex);
//do transaction.
}
即使是一些作爲本VS RHS地址一樣簡單會工作。請務必首先鎖定低位地址。 – 2010-02-12 04:24:23
克隆只有在不復制的情況下才能正常工作,並且我不認爲隱式共享會起作用,但我會看一看。 有趣的方法凱爾。我看不到任何缺陷。 – pomeroy 2010-02-12 20:49:01