2016-11-28 73 views
2

我需要在工作方法中對unique_lock :: owns_lock()進行斷言,但我不'想要傳遞unique_lock作爲參數,而是將其用作靜態變量。但這意味着我不能使用unique_lock來實現其RAII行爲。 有這樣的代碼是否公平:是std :: lock_guard <std :: unique_lock <std::mutex>>有效還是推薦?

namespace 
{ 
    std::mutex gMtx; 
    std::unique_lock<std::mutex> gLock(gMtx, std::defer_lock); 
} 

void foo() 
{ 
    assert(gLock.owns_lock()); 
    // ... 
} 

void bar() 
{ 
    std::lock_guard<std::unique_lock<std::mutex>> lock(gLock); 
    //... 
    foo(); 
    //... 
} 

想法?

+0

這樣做似乎有效。 的#include 「stdafx.h中」 #包括使用命名空間std 的#include 的#include 的#include ; namespace { mutex gMtx; unique_lock gLock(gMtx,defer_lock); } void foo(const string&msg) assert(gLock.owns_lock()); cout << msg << endl; } void bar() { lock_guard > lock(gLock); foo(「bar()」); } int main() { bar(); return 0; } – asterisc

+0

作爲解決方法,您可以將互斥量更改爲recursive_mutex,並將其鎖定在'foo()'中。 –

回答

1

標準不清楚這個構造的有效性。

std::lock_guard的模板參數必須符合BasicLockable requirements,即它必須具有功能lock()unlock()

std::unique_lock有這些功能,這意味着代碼編譯。但是,它們不能像BasicLockable所要求的那樣工作。 unlock()應該拋出異常,但std::unique_lock::unlock()可能會拋出異常。據此,使用std::lock_guard<std::unique_lock<std::mutex>>應該是未定義的行爲。

但是,由於Holt在評論中指出,該標準還指出unique_lock符合BasicLockable要求。所以目前還不清楚行爲是否定義。如果您可以保證unlock()不會丟失(互斥體在lock_guard被銷燬之前未在任何地方解鎖),它可能會在實踐中發揮作用。

+0

標準中有一個註釋說*「[注意:'unique_lock '符合'BasicLockable'的要求[...]]」*,但正如您所指出的那樣,std :: unique_lock :: unlock '不符合'BasicLockable :: unlock'的要求,這有點奇怪... – Holt

+0

我把這個明顯的衝突發佈到了[std-discussion](https://isocpp.org/forums/iso-c-standard -discussion?place = msg%2Fstd-discussion%2F7FELSZvOX3c%2FHbsrjeSNCAAJ)郵件列表。我的感覺(在看到任何答案之前)是沒問題的,因爲'std :: unique_lock :: unlock()'拋出的唯一方法就是它[不擁有鎖](http://eel.is /c++draft/thread.lock.unique#locking-26.1),'BasicLockable'具有調用'unlock()'[當前執行代理擁有鎖]的先決條件(http://eel.is/ C++草案/ thread.req.lockable.basic#3)。 – TBBle

0

根據當前的C++ standard draft,這看起來是有效的,同樣的文本適用於C++11,只有一個段落編號更改。

The thing passed as the template argument to std::lock_guard must be a BasicLockable

BasicLockable指定兩件事情:

  1. lock(),它沒有要求或限制超出要麼獲取鎖拋出異常。
  2. unlock(),只能在鎖定時才能調用,不能失敗,並且不能拋出異常

unique_lock::lock似乎滿足第一個條款,但請參閱下面的分隔線。

unique_lock::unlock滿足第二條的要求,理由是其下unique_lock::unlock可能拋出的唯一情況是,如果鎖定目前尚未舉行,並BasicLockable要求時unlock被稱爲持有鎖。

這與我在將此讀數提交到isocpp.org std-discussion郵件列表時收到的唯一回復相匹配。


如果unique_lock已經舉行,看來對於BasicLockable的要求被違反,作爲當前execution agent持有鎖,拋出一個異常。由於確切的措詞是

如果引發異常,則不應獲取當前執行代理的鎖定。

人們可以說,鎖不收購,因爲它已經舉行。

相關問題