c++ - std::lock_guard 不会解锁

标签 c++ multithreading c++11 mutex

我试图在以下代码中锁定我的互斥量列表,以便一次只有一个线程可以搜索、解锁、锁定或修改它。

#include <mutex>
#include <map>
#include <memory>
#include <vector>
#include <thread>
#include <atomic>
#include <iostream>
#include <Windows.h>

struct MoveableMutex
{
    std::mutex m;
    MoveableMutex() {}
    MoveableMutex(MoveableMutex const&) {}
    MoveableMutex& operator = (MoveableMutex const&) { return *this; }
};

class Locks
{
    private:
        static std::mutex map_lock;
        static std::uint32_t lock_count;
        std::map<std::uint32_t, MoveableMutex> locklist;

    public:
        std::uint32_t AddLock();
        void RemoveLock(std::uint32_t ID);
        void Lock(std::uint32_t ID);
        bool TryLock(std::uint32_t ID);
        void Unlock(std::uint32_t ID);
};

std::uint32_t Locks::lock_count = 0;
std::mutex Locks::map_lock;

std::uint32_t Locks::AddLock()
{
    std::lock_guard<std::mutex> guard(map_lock);
    locklist.insert(std::make_pair(++lock_count, MoveableMutex()));
    return lock_count;
}

void Locks::RemoveLock(std::uint32_t ID)
{
    std::lock_guard<std::mutex> guard(map_lock);
    auto it = locklist.find(ID);
    if (it != locklist.end())
    {
        it->second.m.unlock();
        locklist.erase(it);
    }
}

void Locks::Lock(std::uint32_t ID)
{
    std::lock_guard<std::mutex> guard(map_lock);
    auto it = this->locklist.find(ID);
    if (it != this->locklist.end())
    {
        it->second.m.lock();
    }
}

bool Locks::TryLock(std::uint32_t ID)
{
    std::lock_guard<std::mutex> guard(map_lock);
    auto it = this->locklist.find(ID);
    if (it != this->locklist.end())
    {
        return it->second.m.try_lock();
    }
    return false;
}

void Locks::Unlock(std::uint32_t ID)
{
    std::lock_guard<std::mutex> guard(map_lock);
    auto it = this->locklist.find(ID);
    if (it != locklist.end())
    {
        it->second.m.unlock();
    }
}

int main()
{
    Locks locklist;
    int i = locklist.AddLock();
    std::atomic<bool> stop(false);
    std::atomic<bool> stop2(false);

    std::thread o([&]
    {
        locklist.Lock(i);
        while(!stop)
        {
            std::cout << "Hey\n";
            Sleep(100);
        }
        locklist.Unlock(i);
    });

    std::thread t([&]
    {
        locklist.Lock(i);
        while(!stop2)
        {
            std::cout << "Hey2\n";
            Sleep(100);
        }
        locklist.Unlock(i);
    });

    Sleep(1000);
    stop = true;
    system("CLS");
    o.join();

    Sleep(1000);
    stop2 = true;
    t.join();
    return 0;
}

但是,Unlock 函数中的 std::lock_guard 会导致死锁。如果我从 Unlock 函数中删除 lock_guard,它就可以正常工作。

lock_guard 没有破坏或解锁是否有原因?

最佳答案

一个线程调用 Lock,最终锁定映射中的互斥量。另一个线程调用 Lock,它锁定 map_lock 然后尝试锁定映射中的互斥锁,并卡在那里(map_lock 仍然持有) .最终,第一个线程退出循环并调用 Unlock,它会卡在等待 map_lock 上。

这里的主要设计缺陷是您有一个线程一个接一个地获取两个锁。这只有在所有线程以相同的顺序获取它们(并以与获取的相反顺序释放)时才安全地工作。但是您的代码在不同的时间以不同的顺序获取它们:这是导致死锁的秘诀。

另请参阅:lock hierarchy

关于c++ - std::lock_guard 不会解锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20626424/

相关文章:

c++ - 我应该使用 cmake 搜索什么 Boost 包才能包含 Boost Function 的代码?

c - 主函数和 pthread 中其他线程之间的互斥锁优先级

multithreading - 如何在后台运行 tshark 命令并使用 python 中的子进程退出它

c++ - 如何使用消息访问mfc控件?

c++ - 与静态方法中的 decltype(*this) 等价?

c++ - 使用默认构造函数调用的网格类不工作 OpenGL C++

c++ - 如果我不遵守无状态自定义分配器教条,会发生最糟糕的情况吗?

C++ 以十六进制检索 Unicode 代码点

c++ - C++ Intellisense 和错误检查问题

c++ - vector 排序算法,只对大于 0 的元素进行排序