删除锁定的互斥体
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';
}
我尝试了这段代码并且它有效。但是我想知道 lock_guard 在 onRecognize 函数中会发生什么,因为互斥量在他被锁定时被删除。所以,我的问题可能是:
在他被锁定在别处时删除互斥量是否危险?
感谢
不要销毁锁定的互斥量。
The behavior is undefined if the mutex is owned by any thread or if any thread terminates while holding any ownership of the mutex.
您有一个基本的并发错误,导致您的代码不可靠。指针 m_mutex
在一个线程中被修改并在另一个线程中使用,并且没有任何类型的同步保护它。
这是灾难性的,即使您无法想象它会失败的方式。但碰巧很容易想象它会失败的方式。考虑:
onRecognize
评估 *myResources[1].m_mutex
但尚未构建锁守卫。
shutdown
获取锁,销毁互斥锁,returns.
onRecognize
尝试在不再存在的锁上构造锁守卫。
- 繁荣。
所以你遇到的问题比任何特定于互斥锁语义的问题都大。
GCC(10.2) 和 Clang(10) 没有删除锁定互斥体的问题,MSVC 19.28 将终止。
{
std::mutex m;
m.lock();
}//std::terminate() - MSVC
我有一个包含多个资源的程序,需要用它们自己的互斥锁来锁定。
在这个程序中,可能会发生 资源 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';
}
我尝试了这段代码并且它有效。但是我想知道 lock_guard 在 onRecognize 函数中会发生什么,因为互斥量在他被锁定时被删除。所以,我的问题可能是:
在他被锁定在别处时删除互斥量是否危险?
感谢
不要销毁锁定的互斥量。
The behavior is undefined if the mutex is owned by any thread or if any thread terminates while holding any ownership of the mutex.
您有一个基本的并发错误,导致您的代码不可靠。指针 m_mutex
在一个线程中被修改并在另一个线程中使用,并且没有任何类型的同步保护它。
这是灾难性的,即使您无法想象它会失败的方式。但碰巧很容易想象它会失败的方式。考虑:
onRecognize
评估*myResources[1].m_mutex
但尚未构建锁守卫。shutdown
获取锁,销毁互斥锁,returns.onRecognize
尝试在不再存在的锁上构造锁守卫。- 繁荣。
所以你遇到的问题比任何特定于互斥锁语义的问题都大。
GCC(10.2) 和 Clang(10) 没有删除锁定互斥体的问题,MSVC 19.28 将终止。
{
std::mutex m;
m.lock();
}//std::terminate() - MSVC