![](/img/trans.png)
[英]How do I make sure only my origninal client is used to make requests to my server?
[英]How do I make sure there is only 1 mutex?
我在這里運行一些線程安全的代碼。 我正在使用互斥鎖來保護需要一次只運行1個線程的代碼段。 我遇到的問題是使用此代碼有時我最終得到2個Mutex對象。 順便說一下,這是一個靜態功能。 如何確保只創建1個互斥對象?
/*static*/ MyClass::GetResource()
{
if (m_mutex == 0)
{
// make a new mutex object
m_mutex = new MyMutex();
}
m_mutex->Lock();
只需在GetResource(),
之外創建m_mutex
GetResource(),
然后再調用它 - 這將刪除實際創建互斥鎖的關鍵部分。
MyClass::Init()
{
m_mutex = new Mutex;
}
MyClass::GetResource()
{
m_mutex->Lock();
...
m_mutex->Unlock();
}
問題是在檢查m_mutex是否為0之后線程可能被中斷,但在創建互斥鎖之前不會中斷,允許另一個線程運行相同的代碼。
不要立即分配給m_mutex。 創建一個新的互斥鎖,然后進行原子比較交換。
您沒有提到您的目標平台,但在Windows上:
MyClass::GetResource()
{
if (m_mutex == 0)
{
// make a new mutex object
MyMutex* mutex = new MyMutex();
// Only set if mutex is still NULL.
if (InterlockedCompareExchangePointer(&m_mutex, mutex, 0) != 0)
{
// someone else beat us to it.
delete mutex;
}
}
m_mutex->Lock();
否則,請使用平台提供的任何比較/交換功能進行替換。
另一種選擇是使用一次性初始化支持,可以在Windows Vista及更高版本上使用,或者只是預先創建互斥鎖(如果可以)。
懶惰的互斥初始化不適合靜態方法; 你需要保證沒有人參加初始化。 以下使用編譯器為類生成單個靜態互斥鎖。
/* Header (.hxx) */
class MyClass
{
...
private:
static mutable MyMutex m_mutex; // Declares, "this mutex exists, somewhere."
};
/* Compilation Unit (.cxx) */
MyMutex MyClass::m_mutex; // The aforementioned, "somewhere."
MyClass::GetResource()
{
m_mutex.Lock();
...
m_mutex.Unlock();
}
其他一些解決方案需要您的其他程序員的額外假設。 例如,使用“call init()”方法,您必須確保調用初始化方法,並且每個人都必須知道此規則。
為什么還要使用指針? 為什么不用不需要動態內存管理的實際實例替換指針? 這避免了競爭條件,並且不會對每次調用函數施加性能影響。
因為它只是為了保護一個特定的代碼段,所以只需在函數內聲明它是靜態的。
static MyClass::GetResource()
{
static MyMutex mutex;
mutex.Lock();
// ...
mutex.Unlock();
變量是具有靜態存儲持續時間的局部變量。 標准中明確規定:
允許實現在靜態或線程存儲持續時間內執行其他塊范圍變量的早期初始化,條件是允許實現在命名空間范圍內靜態初始化具有靜態或線程存儲持續時間的變量(3.6.2)。 否則,在第一次控制通過其聲明時初始化這樣的變量; 這樣的變量在初始化完成后被認為是初始化的。 如果通過拋出異常退出初始化,則初始化未完成,因此下次控制進入聲明時將再次嘗試初始化。 如果控制在初始化變量時同時進入聲明,則並發執行應等待初始化完成。
最后一句話對你特別感興趣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.