我想从两个线程原子地调用某些类的方法。 我有来自第三方库的非安全类,但需要像这样使用这个类:
主线程:
Foo foo;
foo.method1(); // while calling Foo::method1 object foo is locked for another threads
第二个帖子:
foo.method2(); // wait while somewere calling another methods from foo
如何在这种情况下使用std :: atomic?或者可能是另一个解决方案(在调用foo方法之后,排除使用互斥锁和锁定之前和解锁)?
答案 0 :(得分:5)
您不能将std::atomic
与用户定义的类型一起使用,而这些类型并非易于复制,而且标准仅为某些基本类型提供了一组有限的特化。 Here您可以找到std::atomic
的所有标准专精的列表。
您可能需要考虑的一种方法是编写一个通用包装器,它允许您以可线程安全的方式在包装对象上提供可调用对象。 Herb Sutter曾在one of his talks中提出过这些问题:
template<typename T>
class synchronized
{
public:
template<typename... Args>
synchronized(Args&&... args) : _obj{std::forward<Args>(args)...} { }
template<typename F>
void thread_safe_invoke(F&& f)
{
std::lock_guard<std::mutex> lock{_m};
(std::forward<F>(f))(_obj);
}
// ...
private:
T _obj;
std::mutex _m;
};
如果您只想以线程安全的方式调用单个函数,这会产生一些语法开销,但它也允许实现必须以原子方式执行的事务,并且可能包含对同步对象的多个函数调用。
您可以使用它:
int main()
{
synchronized<std::string> s{"Hello"};
s.thread_safe_invoke([&] (auto& s)
{
std::cout << s.size() << " " << (s + s);
});
}
有关更深入的分析和实施指南,您可以参考有关该主题的this article以及this one。
答案 1 :(得分:0)
在不同的主题之间共享std::mutex
。无论您使用foo
,请使用std::unique_lock