我的问题与多线程无锁同步有关。我想知道以下内容:
实现这一目标的一般方法是什么?我在某处读过有关LockFreePrimitives的内容,比如CompareAndExchange(CAS)或DoubleCompareAndExchange(DCA),但没有给出解释? MINIMIZE使用锁的任何方法?
Java / .NET如何实现其并发容器?他们使用锁或无锁同步吗?
提前致谢。
答案 0 :(得分:6)
假设您的算法具有一些特定的可利用功能,以下是一些可以最小化锁定使用的一般方法:
更新单个数字变量时,可以使用非阻塞原语,例如CAS,atomic_increment等。它们通常比经典的阻塞关键部分(lock,mutex)快得多。
< / LI>当一个数据结构由多个线程读取,但只由一个或几个线程写入时,一个明显的解决方案是读写锁,而不是完全锁定。
尝试利用细粒锁定。例如,不是使用单个锁锁定整个数据结构,而是查看是否可以使用多个不同的锁来保护数据结构的不同部分。
如果您依赖锁的隐式内存栅栏效应来确保跨线程可见单个变量,只需使用volatile
1 (如果可用)。 p>
有时,在实践中使用条件变量(和相关的锁定)太慢。在这种情况下,volatile
忙碌旋转效率更高。
此处有关此主题的更多好建议:http://software.intel.com/en-us/articles/intel-guide-for-developing-multithreaded-applications/
另一个SO问题的好读:Lock-free multi-threading is for real threading experts(不要被标题吓到)。
最近讨论过的atomic_decrement的无锁Java实现:Starvation in non-blocking approaches
1 此处volatile
的使用适用于Java等语言,其中volatile
已在内存模型中定义了语义,但未在C {C ++中定义{{1}在引入跨线程内存模型之前,并没有与它集成。这些语言中提供了类似的结构,例如C ++中的各种std::memory_order
说明符。
答案 1 :(得分:1)
有一些有用的方法可以使用无锁同步(例如@Tudor提到的那些)。但是我想警告一件事 - 无锁同步化并不构成。
例如,您可能有一个由compare&amp; swap维护的整数,并且没关系。您可能还有一个由无锁算法维护的队列(这有点棘手,但它有很好的算法),队列也可以。
但是如果你试图使用计数器来计算队列中的元素,你会得到错误的答案。有时会添加一个元素,但计数器还没有反映它(反之亦然),如果你信任它就可以得到bug(例如你可能会尝试添加到一个完整的队列)。
简而言之 - 您可以让每个元素与自身保持一致,但彼此不一致。
答案 2 :(得分:0)
比较和交换是有用的,但有一种更简单(所谓的'无锁')技术,在某些可能有用的生产者/消费者用例中很有用,所以我会提到它。
想象一下,你有一个写入缓冲区的函数doWork()。
这只能起作用,因为A只读取而B只写入,但这种用例对于“后台工作者”线程来说相当常见。这只能肯定适用于Java或C#,其中volatile带有保证。