gpt4 book ai didi

c++ - 避免单线程死锁

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:14:30 25 4
gpt4 key购买 nike

我有以下问题:我有一个类需要防止来自不同线程的同时访问。该类有两个方法:lock() 和 unlock() 使用(g_mutex_lock/g_mutex_unlock 和每个对象 GMutex)。现在锁定方法如下所示:

void Object::method()
{
lock();
// do stuff modifying the object
unlock();
}

现在假设我有两个这种类型的方法,method1()method2(),我一个接一个地调用它们:

object.method1();
// but what if some other thread modifies object in between
object.method2();

我尝试在这个 block 之前锁定对象并再次解锁它,但在这种情况下即使是单线程也会出现死锁,因为 GMutex 不知道它已经被同一个线程锁定了。一种解决方案是修改方法以接受额外的 bool 以确定对象是否已被锁定。但是有没有更优雅的概念呢?或者这是整体设计理念的缺点?

最佳答案

其他回复和评论中提到的递归互斥锁解决方案会工作得很好,但根据我的经验,它会导致代码更难维护,因为一旦你切换到递归互斥锁,它很容易被滥用并锁定到处都是。

相反,我更喜欢重新组织代码,这样锁定一次就足够了。在您的示例中,我将按如下方式定义类:

class Object {
public:
void method1() {
GMutexLock scopeLock(&lock);
method1_locked();
}
void method2() {
GMutexLock scopeLock(&lock);
method2_locked();
}
void method1_and_2() {
GMutexLock scopeLock(&lock);
method1_locked();
method2_locked();
}

private:
void method1_locked();
void method2_locked();

GMutex lock;
};

您的方法的“锁定”版本是私有(private)的,因此它们只能从类内部访问。该类负责在没有锁定的情况下永远不会调用这些。

从外部您可以选择三种调用方法,具体取决于您要运行的方法。

请注意,我所做的另一项改进是不使用显式锁定原语,而是间接使用范围来锁定和解锁。这就是 GMutexLock 所做的。此类的示例实现如下:

class GMutexLock {
private:
GMutex* m;

GMutexLock(const GMutexLock &mlock); // not allowed
GMutexLock &operator=(const GMutexLock &); // not allowed

public:
GMutexLock(GMutex* mutex) {
m = mutex;
g_mutex_lock(m);
}

~GMutexLock() {
g_mutex_unlock(m);
}
};

关于c++ - 避免单线程死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20776172/

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