gpt4 book ai didi

c++ - 如何实现多线程访问的类锁对象

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

假设我有以下过度简化的类,并希望保护资源免受多线程访问。我怎样才能像类锁一样合并某些东西,其中每个进入公共(public)接口(interface)的“入口点”首先必须在被允许使用该接口(interface)之前获得一个类锁?

class MyClass
{
public:
void A();
void B();
void C();
void D();
void E();

private:
SharedResource _res;
}

void MyClass::A()
{
B();
C();
D();
E();
}

void MyClass::B()
{
// do sth with _res
}

void MyClass::C()
{
// do sth with _res
}

void MyClass::D()
{
// do sth with _res
}

void MyClass::E()
{
// do sth with _res
}

我可以通过在每个方法中锁定一个类互斥体来实现,然后有两个版本的方法 B-E,如下所示:

void MyClass::A()
{
std::lock<std::mutex> lock(_mutex);
B_mtx();
C_mtx();
D_mtx();
E_mtx();
}

void MyClass::B()
{
std::lock<std::mutex> lock(_mutex);
B_mtx();
}

void MyClass::B_mtx()
{
// logic of B
}

// ...

但这实际上看起来更麻烦,在更大、更复杂的接口(interface)中更难纠正,而不是要求客户端首先向类请求一个锁对象,然后被允许保存地使用类的接口(interface),直到他再次释放锁。有没有办法轻松实现这个?我可以只使用方法 getLock 在类互斥体上创建锁并使用 move-assigment 将其发送给客户端吗?调用方法时如何在类内部确保调用者拥有锁?

最佳答案

如果您需要您的类是线程安全的,也就是说,只能在锁下使用,您可以让所有公共(public)函数接受对 std::lock< 的引用(最好包装在自定义对象中,或者至少是一个 typedef):

class MyClass
{
mutable std::mutex mtx;

public:
using Lock = std::unique_lock<std::mutex>;

void A(Lock &l)
{
assert(l.mutex() == mtx);
// ...
}

void B(Lock &l)
{
assert(l.mutex() == mtx);
// ...
}

Lock getLock() const
{ return Lock(mtx); }

void releaseLock(Lock &&l) const
{ Lock l2 = std::move(l); }
};

但是,另一种方法是让类忽略锁定问题,而是为其提供一个线程安全的包装器。 Herb Sutter 在他的一次演讲中提出了一个非常相似的想法(1):

class MyClass
{
public:
void A()
{
//...
}

void B()
{
//...
}
};

class MyClass_ThreadSafe
{
MyClass m;
std::mutex mtx;

public:
template <class Operation>
auto call(Operation o) -> decltype(o(m))
{
std::unique_lock l(mtx);
return o(m);
}
};

// Usage:

MyClass_ThreadSafe mc;
mc.call(
[](MyClass &c)
{
c.A();
c.B();
}
);

(1) C++ and Beyond 2012 — Herb Sutter: C++ Concurrency从第 36 分钟开始。

关于c++ - 如何实现多线程访问的类锁对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33895071/

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