我创建了以下类,它提供了一个acquire_lock()和release_lock()函数
class LockableObject {
public:
void acquire_lock() {
std::unique_lock<std::mutex> local_lock(m_mutex);
m_lock = std::move(local_lock);
}
void release_lock() {
m_lock.unlock();
}
private:
std::mutex m_mutex;
std::unique_lock<std::mutex> m_lock;
};
Run Code Online (Sandbox Code Playgroud)
这个类提供了一个acquire_lock和release_lock函数。我有多个线程访问同一个对象并acquire_lock在执行任何操作之前调用 ,然后调用release_lock一次,如下所示。
void ThreadFunc(int ID, LockableObject* lckbleObj)
{
for (int i = 0; i < 1000; i++)
{
lckbleObj->acquire_lock();
std::cout << "Thread with ID = " << ID << "doing work" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
lckbleObj->release_lock();
}
}
void main()
{
const int numThreads = 10;
std::thread workerThreads[numThreads];
LockableObject *testObject = new LockableObject();
for (int i = 0; i < numThreads; i++)
{
workerThreads[i] = std::thread(ThreadFunc, i, testObject);
}
for (int i = 0; i < numThreads; i++)
{
workerThreads[i].join();
}
}
Run Code Online (Sandbox Code Playgroud)
在acquire_lock函数中,我首先尝试通过在构造函数中传递它 ( ) 来m_mutex使用本地堆栈std::unique_lock对象锁定底层互斥锁 ( ) m_mutex。我假设一旦std::unique_lock返回的构造函数锁定了互斥锁,然后我将unique_lock堆栈上的 移到成员变量m_lock。
该程序在某些基本方面存在缺陷,在调用期间release_lock将导致"unlock of unowned mutex",我似乎缺少一些基本的东西std::unique_lock,正在寻找人来纠正我的理解。
请参阅我std::defer_lock对构造函数中缺少的评论。但是您的代码中也存在竞争条件。
该acquire_lock函数修改互斥锁的m_lock保护不足m_mutex。因此,为了确保线程安全,m_lock除了持有 之外,其他线程都不能修改m_mutex。
但是该release_lock函数m_lock在释放该互斥锁时会进行修改。因此,您在 上没有适当的同步m_lock。
这有点难以理解。这是问题代码:
m_lock.unlock();
Run Code Online (Sandbox Code Playgroud)
请注意,当此函数被输入时,m_mutex被锁定,但在其执行期间,它以没有特定保证的顺序修改m_lock和释放m_mutex。而是m_mutex保护m_lock。所以这是一种竞争条件,是不允许的。
它可以固定如下:
void release_lock() {
std::unique_lock<std::mutex> local_lock = std::move(m_lock);
local_lock.unlock();
}
Run Code Online (Sandbox Code Playgroud)
现在,这第一行代码修改m_lock但完全m_mutex保持运行。这避免了竞争条件。
unlock如果需要,可以将其移除。的析构函数local_lock会这样做。
顺便说一下,我建议更改 API。不是提供锁定和解锁调用,而是有一种方法来创建一个拥有此对象锁定的对象。std::unique_lock<LockableObject>如果你愿意,你甚至可以使用。为什么要创建比标准提供的 API 更糟糕的新 API?
| 归档时间: |
|
| 查看次数: |
1430 次 |
| 最近记录: |