[英]Deleting a mutex that is locked
我有一個包含多個資源的程序,需要由它們自己的互斥鎖鎖定。
在這個程序中,可能會發生在資源 A 的互斥鎖被鎖定時,資源 A在另一個線程中被刪除。
以下代碼嘗試重現我嘗試完成的邏輯:
#include <thread>
#include <mutex>
#include <iostream>
#include <map>
int g_i = 0;
struct Resource
{
std::mutex* m_mutex;
};
std::map<unsigned int, Resource> myResources;
std::mutex g_i_mutex; // protects g_i
void shutdown()
{
std::cout << "shutdown -> myMap.size = : " << myResources.size() << std::endl;
std::lock_guard<std::mutex> lock(*myResources[1].m_mutex);
++g_i;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
delete myResources[1].m_mutex;
myResources[1].m_mutex = NULL;
myResources.erase(1);
std::cout << "shutdown -> myMap.size = : " << myResources.size() << std::endl;
std::cout << "shutdown : " << g_i << '\n';
}
void onRecognize()
{
std::cout << "onRecognize -> myMap.size = : " << myResources.size() << std::endl;
std::lock_guard<std::mutex> lock(*myResources[1].m_mutex);
std::cout << "onRecognize -> myMap.size = : " << myResources.size() << std::endl;
++g_i;
std::cout << "onRecognize : " << g_i << '\n';
}
int main()
{
std::cout << __func__ << ": " << g_i << '\n';
Resource myStruct;
myStruct.m_mutex = new std::mutex();
myResources[1] = myStruct;
std::thread t1(shutdown);
std::thread t2(onRecognize);
t1.join();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
t2.join();
std::cout << __func__ << ": " << g_i << '\n';
}
我試過這段代碼,它的工作原理。 但我想知道onRecognize函數中的lock_guard會發生什么,因為互斥鎖在他被鎖定時被刪除。 所以,我的問題可能是:
當他被鎖定在其他地方時刪除互斥鎖是否危險?
謝謝
不要在鎖定時銷毀互斥鎖。
如果互斥鎖由任何線程擁有,或者任何線程在持有互斥鎖的任何所有權時終止,則行為未定義。
您有一個基本的並發錯誤,導致您的代碼不可靠。 指針m_mutex
在一個線程中被修改並在另一個線程中使用,並且沒有任何類型的同步來保護它。
即使您無法想象它會失敗的方式,這也是災難性的。 但碰巧很容易想象它可能失敗的方式。 考慮:
onRecognize
評估*myResources[1].m_mutex
但尚未構建鎖保護。shutdown
獲取鎖,銷毀互斥鎖,然后返回。onRecognize
嘗試在不再存在的鎖上構造鎖保護。因此,您遇到的問題比任何特定於互斥體語義的問題都大。
GCC(10.2) 和 Clang(10) 沒有刪除鎖定互斥鎖的問題,MSVC 19.28 將終止。
{
std::mutex m;
m.lock();
}//std::terminate() - MSVC
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.