简体   繁体   English

原子类对象方法的用法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM