gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 10:46:22 24 4
gpt4 key购买 nike

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

#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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com