原子类对象方法用法

时间:2015-01-20 17:23:54

标签: c++ multithreading c++11 atomic

我想从两个线程原子地调用某些类的方法。 我有来自第三方库的非安全类,但需要像这样使用这个类:

主线程:

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方法之后,排除使用互斥锁和锁定之前和解锁)?

2 个答案:

答案 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

打包电话