问题
I have a program with multiple resources that needs to be lock by their own mutex.
In this program, it might happen that while mutex for resource A is locked, resource A is deleted in another thread.
The following code try to reproduce the logic of what I try to accomplish :
#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';
}
I tried this snippet of code and it works. But I am wondering what happen with lock_guard in onRecognize function, because the mutex is being deleted while he is locked. So, my question might be :
Does deleting a mutex while he is locked somewhere else is dangerous?
Thx
回答1:
Don't destroy a mutex while it is locked.
The behavior is undefined if the mutex is owned by any thread or if any thread terminates while holding any ownership of the mutex.
http://en.cppreference.com/w/cpp/thread/mutex/~mutex
回答2:
You have a fundamental concurrency error that renders your code unreliable. The pointer m_mutex
is modified in one thread and used in another, and no synchronization of any kind protects it.
This is catastrophic even if you can't imagine a way it can fail. But it happens to be very easy to imagine ways it can fail. Consider:
onRecognize
evaluates*myResources[1].m_mutex
but hasn't constructed the lock guard yet.shutdown
acquires the lock, destroys the mutex, and returns.onRecognize
tries to construct the lock guard on a lock that no longer exists.- Boom.
So you have bigger problems than anything specific to the semantics of mutexes.
来源:https://stackoverflow.com/questions/34030156/deleting-a-mutex-that-is-locked