[英]Atomic class object methods usage
I want to call methods of some class atomically from two threads. 我想从两个线程中自动调用某个类的方法。 I have non-thead-safe class, from third-party library, but need to use this class like that:
我有来自第三方库的非头部安全类,但需要使用此类:
Main thread: 主线程:
Foo foo;
foo.method1(); // while calling Foo::method1 object foo is locked for another threads
Second thread: 第二个线程:
foo.method2(); // wait while somewere calling another methods from foo
How to use std::atomic at this situation? 在这种情况下如何使用std :: atomic? Or may be another solution (exclude use mutex and lock before and unlock after calling methods from foo)?
或者是另一种解决方案(排除从foo调用方法之前使用互斥锁和锁定,以及在从foo调用方法之后使用解锁)?
You cannot use std::atomic
with user-defined types that are not trivially copyable, and the Standard only provides a limited set of specializations for certain fundamental types. 您不能将
std::atomic
与无法轻松复制的用户定义类型一起使用,并且标准仅对某些基本类型提供了一组有限的专业化设置。 Here you can find the list of all the standard specializations of std::atomic
. 在这里,您可以找到
std::atomic
的所有标准专业列表。
One approach you may want to consider is to write a general-purpose wrapper that lets you provide callable objects to be executed in a thread-safe manner on the wrapped object. 您可能要考虑的一种方法是编写一个通用包装器,该包装器使您可以提供可调用对象,以便在该包装对象上以线程安全的方式执行该对象。 Something along these lines was once presented by Herb Sutter in one of his talks :
赫伯·萨特(Herb Sutter)在他的一次演讲中曾提出过类似的观点:
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;
};
This incurs some syntactic overhead in case you only want to call a single function in a thread-safe manner, but it also allows realizing transactions that must be performed atomically and may consist of more than one function call on the synchronized object. 万一您只想以线程安全的方式调用单个函数,这会产生一些语法开销,但是它也允许实现必须原子执行的事务,并且可能包含对同步对象的多个函数调用。
This is how you could use it: 这是您可以使用的方式:
int main()
{
synchronized<std::string> s{"Hello"};
s.thread_safe_invoke([&] (auto& s)
{
std::cout << s.size() << " " << (s + s);
});
}
For a deeper analysis and implementation guidance, you may refer to this article on the subject as well as this one . 为了更深入的分析和实施指导,您可以参考这篇文章的主题以及这一个 。
Share a std::mutex
between the different threads. 在不同线程之间共享一个
std::mutex
。 Where ever you use foo
, wrap the calls with a std::unique_lock
在任何使用
foo
地方,都用std::unique_lock
包裹调用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.