std :: lock_guard不会解锁

 男人好好疼h爱你的女人吧 发布于 2023-02-09 22:10

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

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

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 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 guard(map_lock);
    locklist.insert(std::make_pair(++lock_count, MoveableMutex()));
    return lock_count;
}

void Locks::RemoveLock(std::uint32_t ID)
{
    std::lock_guard 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 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 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 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 stop(false);
    std::atomic 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;
}

但是,std::lock_guardUnlock函数内部,它会导致死锁.如果我从解锁功能中删除lock_guard,它可以正常工作.

lock_guard没有破坏或解锁的原因吗?

1 个回答
  • 一个线程调用Lock,最终锁定映射中的互斥锁.另一个线程调用Lock,然后锁定map_lock然后尝试锁定地图中的互斥锁,然后卡在那里(map_lock仍然保持).最终,第一个线程退出循环并调用Unlock,等待等待map_lock.

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

    另请参见:锁定层次结构

    2023-02-09 22:25 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有