簡體   English   中英

跨線程的unique_lock?

[英]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_lockunique_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM