[英]unique_lock across threads?
我在構思unique_lock
如何跨線程運行時遇到了一些麻煩。 我試圖快速舉例來重新創建一些我通常會使用condition_variable
的東西。
#include <mutex>
#include <thread>
using namespace std;
mutex m;
unique_lock<mutex>* mLock;
void funcA()
{
//thread 2
mLock->lock();//blocks until unlock?Access violation reading location 0x0000000000000000.
}
int _tmain(int argc, _TCHAR* argv[])
{
//thread 1
mLock = new unique_lock<mutex>(m);
mLock->release();//Allows .lock() to be taken by a different thread?
auto a = std::thread(funcA);
std::chrono::milliseconds dura(1000);//make sure thread is running
std::this_thread::sleep_for(dura);
mLock->unlock();//Unlocks thread 2's lock?
a.join();
return 0;
}
不應同時從多個線程訪問unique_lock
。 它不是以這種方式設計為線程安全的。 相反,多個unique_lock
(局部變量)引用相同的全局mutex
。 只有mutex
本身可以被多個線程同時訪問。 即便如此,我的陳述也排除了~mutex()
。
例如,有人知道多個線程可以訪問mutex::lock()
,因為它的規范包括以下內容:
同步:對同一對象的先前
unlock()
操作應與 (4.7)此操作同步 。
其中同步是4.7 [intro.multithread](及其子條款)中定義的術語。
這看起來不太好。 首先, release
是“在沒有解鎖它的情況下解除互斥鎖的關聯”,這不太可能是你想要在那個地方做的事情。 它基本上意味着你的unique_lock<mutex>
不再有mutex
unique_lock<mutex>
- 這將使它變得毫無用處 - 可能是你獲得“訪問沖突”的原因。
編輯:經過一些“按摩”你的代碼,並說服g ++ 4.6.3做我想做的事情(因此#define _GLIBCXX_USE_NANOSLEEP
),這是一個有效的例子:
#define _GLIBCXX_USE_NANOSLEEP
#include <chrono>
#include <mutex>
#include <thread>
#include <iostream>
using namespace std;
mutex m;
void funcA()
{
cout << "FuncA Before lock" << endl;
unique_lock<mutex> mLock(m);
//thread 2
cout << "FuncA After lock" << endl;
std::chrono::milliseconds dura(500);//make sure thread is running
std::this_thread::sleep_for(dura); //this_thread::sleep_for(dura);
cout << "FuncA After sleep" << endl;
}
int main(int argc, char* argv[])
{
cout << "Main before lock" << endl;
unique_lock<mutex> mLock(m);
auto a = std::thread(funcA);
std::chrono::milliseconds dura(1000);//make sure thread is running
std::this_thread::sleep_for(dura); //this_thread::sleep_for(dura);
mLock.unlock();//Unlocks thread 2's lock?
cout << "Main After unlock" << endl;
a.join();
cout << "Main after a.join" << endl;
return 0;
}
不知道為什么你需要使用new
來創建鎖定'。 當然unique_lock<mutex> mlock(m);
應該做的伎倆(以及相應的mLock->
更改為mLock.
當然)。
鎖只是一個自動防護裝置,以安全和理智的方式操作互斥鎖。
你真正想要的是這段代碼:
std::mutex m;
void f()
{
std::lock_guard<std::mutex> lock(m);
// ...
}
這有效地“同步”了對f
調用,因為進入它的每個線程都會阻塞,直到它設法獲得互斥鎖。
unique_lock
只是lock_guard
一個增強版本:它可以構造為解鎖,移動(感謝,@ MikeVine),它本身就是一個“可鎖定對象”,就像互斥鎖本身一樣,所以它可以用作例子在variadic std::lock(...)
以無死鎖的方式一次鎖定多個東西,它可以由std::condition_variable
(感謝,@ syam)管理。
但除非你有充分的理由使用unique_lock
, unique_lock
更喜歡使用lock_guard
。 一旦你需要升級到unique_lock
,你就會知道原因。
作為旁注,上面的答案跳過了互斥鎖的立即鎖定和延遲鎖定之間的區別:
#include<mutex>
::std::mutex(mu);
auto MyFunction()->void
{
std::unique_lock<mutex> lock(mu); //Created instance and immediately locked the mutex
//Do stuff....
}
auto MyOtherFunction()->void
{
std::unique_lock<mutex> lock(mu,std::defer_lock); //Create but not locked the mutex
lock.lock(); //Lock mutex
//Do stuff....
lock.unlock(); //Unlock mutex
}
MyFunction()顯示廣泛使用的立即鎖定,而MyOtherFunction()顯示延遲鎖定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.