我想从两个线程原子地调用某个类的方法。 我有来自第三方库的非头部安全类,但需要像这样使用此类:
主线程:
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 调用方法之前使用互斥锁和锁定并在调用方法之后解锁)?
最佳答案
您不能将 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 .
关于c++ - 原子类对象方法的用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28051472/