简体   繁体   English

std :: lock_guard不会解锁

[英]std::lock_guard won't unlock

I'm trying to lock my list of mutexes in the following code so that only one thread can search it, unlock, lock or modify it at a time. 我正在尝试在以下代码中锁定互斥锁列表,以便一次只能有一个线程可以搜索,解锁,锁定或修改它。

#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;
}

However, with the std::lock_guard inside the Unlock function, it causes a deadlock. 但是,在Unlock函数中使用std::lock_guard ,它将导致死锁。 If I remove the lock_guard from the Unlock function, it works fine. 如果我从“解锁”功能中删除了lock_guard,它将正常工作。

Is there a reason the lock_guard isn't destructing or unlocking? 有没有原因lock_guard没有破坏或解锁?

One thread calls Lock , which ends up locking the mutex in the map. 一个线程调用Lock ,最终将互斥锁锁定在映射中。 The other thread calls Lock , which locks map_lock then tries to lock the mutex in the map, and gets stuck there (with map_lock still held). 另一个线程调用Lock ,它锁定map_lock然后尝试将互斥锁锁定在地图中,并卡在那里(仍然保持map_lock )。 Eventually, the first thread gets out of the loop and calls Unlock , which gets stuck waiting on map_lock . 最终,第一个线程退出循环并调用Unlock ,该线程在map_lockmap_lock

The main design flaw here is that you have a thread acquire two locks, one after another. 这里的主要设计缺陷是,您的线程需要两个锁,一个接一个。 This only works safely if all threads acquire them in the same order (and release in reverse order of acquiring). 仅当所有线程以相同顺序获取它们(并以获取的相反顺序释放它们)时这才安全地工作。 But your code acquires them in different order at different times: that's a recipe for a deadlock. 但是您的代码在不同的时间以不同的顺序获取它们:这是造成僵局的秘诀。

See also: lock hierarchy 另请参阅: 锁定层次结构

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM