原子类对象方法用法
Posted
技术标签:
【中文标题】原子类对象方法用法【英文标题】:Atomic class object methods usage 【发布时间】:2015-01-20 17:23:53 【问题描述】:我想从两个线程原子地调用某个类的方法。 我有来自第三方库的非头部安全类,但需要像这样使用这个类:
主线程:
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 方法之前使用互斥锁和解锁)?
【问题讨论】:
【参考方案1】:您不能将std::atomic
与不可简单复制的用户定义类型一起使用,并且该标准仅为某些基本类型提供了一组有限的特化。 Here 你可以找到std::atomic
的所有标准专业列表。
您可能要考虑的一种方法是编写一个通用包装器,它允许您提供可调用对象,以便在包装对象上以线程安全的方式执行。 Herb Sutter 曾经在one of his talks 中提出过类似的内容:
template<typename T>
class synchronized
public:
template<typename... Args>
synchronized(Args&&... args) : _objstd::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。
【讨论】:
【参考方案2】:在不同线程之间共享std::mutex
。无论您在哪里使用foo
,都可以使用std::unique_lock
包装调用
【讨论】:
另一种解决方案?使用互斥锁是可以的,但需要更多的代码行(每次调用 1-2 行)。 @Anton 你可以将Foo
包装在一个SynchronisedFoo
类中,如果冗长是一个普遍的问题,它会为它包装的每个方法锁定一个互斥锁。以上是关于原子类对象方法用法的主要内容,如果未能解决你的问题,请参考以下文章
Juc15_基本AtomicInteger数组引用AtomicStampedReference对象的属性修改原子类AtomicIntegerFieldUp 原子操作增强类LongAdder