Java 并发:CAS 与锁定
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2664172/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Concurrency: CAS vs Locking
提问by Prine
I'm reading the Book Java Concurrency in Practice. In chapter 15, they are talking about the nonblocking algorithms and the compare-and-swap(CAS) method.
我正在阅读《Java 并发实践》一书。在第 15 章中,他们讨论了非阻塞算法和比较和交换(CAS) 方法。
It is written that CAS perform much better than the locking methods. I want to ask the people who already worked with both of these concepts and would like to hear when you are preferring which one of these concepts? Is it really so much faster?
CAS 的性能比锁定方法好得多。我想问那些已经使用过这两个概念并想听听您何时更喜欢这些概念中的哪一个的人?真的有那么快吗?
For me, the usage of locks is much clearer and easier to understand and maybe even better to maintain (please correct me if I am wrong). Should we really focus on creating our concurrent code related to CAS than locks to get a better performance boost or is sustainability more important?
对我来说,锁的用法更清晰易懂,甚至更好维护(如果我错了,请纠正我)。我们真的应该专注于创建与 CAS 相关的并发代码而不是锁以获得更好的性能提升还是可持续性更重要?
I know there is maybe not a strict rule when to use what. But I just would like to hear some opinions, experiences with the new concept of CAS.
我知道何时使用什么可能没有严格的规则。但我只是想听听对CAS新概念的一些意见和经验。
采纳答案by Marcelo Cantos
CAS is generally much faster than locking, but it does depend on the degree of contention. Because CAS may force a retry if the value changes between reading and comparing, a thread can theoretically get stuck in a busy-wait if the variable in question is being hit hard by many other threads (or if it is expensive to compute a new value from the old value (or both)).
CAS 通常比锁定快得多,但它确实取决于争用程度。因为如果值在读取和比较之间发生变化,CAS 可能会强制重试,如果相关变量受到许多其他线程的重击(或者如果计算新值的成本很高),则理论上线程可能会陷入忙等待从旧值(或两者))。
The main issue with CAS is that it is much more difficult to program with correctly than locking. Mind you, locking is, in turn, much harder to use correctly than message-passing or STM, so don't take this as a ringing endorsement for the use of locks.
CAS 的主要问题是正确编程比锁定要困难得多。请注意,反过来,锁定比消息传递或STM更难正确使用,因此不要将其视为使用锁定的响铃认可。
回答by John Vint
You can look at the numbers between a ConcurrentLinkedQueue
and a BlockingQueue
. What you will see is that CASis noticeably faster under moderate (more realistic in real world applications) thread contention.
您可以查看 aConcurrentLinkedQueue
和 a之间的数字BlockingQueue
。您将看到的是,在中等(在现实世界应用程序中更现实)线程争用情况下,CAS的速度明显更快。
The most attractive property of nonblockingalgorithms is the fact that if one thread fails (cache miss, or worse, seg fault) then other threads will not notice this failure and can move on. However, when acquiring a lock, if the lock holding thread has some kind of OS failure, every other thread waiting for the lock to be freed will be hit with the failure also.
非阻塞算法最吸引人的特性是,如果一个线程失败(缓存未命中,或者更糟的是,段错误),那么其他线程将不会注意到这个失败并且可以继续前进。但是,在获取锁时,如果持有锁的线程出现某种操作系统故障,则每个其他等待释放锁的线程也会遇到故障。
To answer your questions, yes, nonblocking thread-safe algorithms or collections (ConcurrentLinkedQueue
, ConcurrentSkipListMap/Set
) can be significantly faster than their blocking counterparts. As Marcelo pointed out though, getting nonblocking algorithms correct is very difficult and requires a lot of consideration.
要回答您的问题,是的,非阻塞线程安全算法或集合 ( ConcurrentLinkedQueue
, ConcurrentSkipListMap/Set
) 可以比阻塞对应算法快得多。不过正如 Marcelo 指出的那样,让非阻塞算法正确是非常困难的,需要很多考虑。
You should read about the Michael and Scott Queue, this is the queue implementation for ConcurrentLinkedQueue
and explains how to handle a two-way, thread-safe, atomic function with a single CAS.
您应该阅读Michael 和 Scott Queue,这是队列实现ConcurrentLinkedQueue
并解释了如何使用单个CAS处理双向、线程安全、原子函数。
回答by Victor Sorokin
There's good book strongly related to the topic of lock-free concurrency: "The Art of multi-processor programming" by Maurice Herlihy
有一本与无锁并发主题密切相关的好书:Maurice Herlihy 的“多处理器编程的艺术”
回答by Brian Goetz
The relative speed of the operations is largely a non-issue. What is relevant is the difference in scalability between lock-based and nonblocking algorithms. And if you're running on a 1 or 2 core system, stop thinking about such things.
操作的相对速度在很大程度上不是问题。相关的是基于锁和非阻塞算法之间可伸缩性的差异。如果您在 1 或 2 核系统上运行,请停止考虑此类事情。
Nonblocking algorithms generally scale better because they have shorter "critical sections" than lock-based algorithms.
非阻塞算法通常可以更好地扩展,因为它们比基于锁的算法具有更短的“关键部分”。
回答by Mark Bednarczyk
If you are looking for a real world comparison, here is one. Our application has two (2) threads 1) A reader thread for network packet capture and 2) a consumer thread that takes the packet, counts it and reports statistics.
如果您正在寻找真实世界的比较,这里有一个。我们的应用程序有两 (2) 个线程 1) 一个用于网络数据包捕获的读取器线程和 2) 一个接收数据包、对其进行计数并报告统计信息的消费者线程。
Thread #1 exchanges a single packet at a time with thread #2
线程 #1 一次与线程 #2 交换一个数据包
Result #1- uses a custom CAS based exchange using the same principles as SynchronousQueue, where our class is called CASSynchronousQueue:
结果 #1- 使用基于自定义 CAS 的交换,使用与SynchronousQueue相同的原则,我们的类称为CASSynchronousQueue:
30,766,538 packets in 59.999 seconds :: 500.763Kpps, 1.115Gbps 0 drops
libpcap statistics: recv=61,251,128, drop=0(0.0%), ifdrop=0
Result #2- when we replace our CAS implementation with the standard java SynchronousQueue:
结果 #2- 当我们用标准的 java SynchronousQueue替换我们的 CAS 实现时:
8,782,647 packets in 59.999 seconds :: 142.950Kpps, 324.957Mbps 0 drops
libpcap statistics: recv=69,955,666, drop=52,369,516(74.9%), ifdrop=0
I don't think the difference in performance couldn't be any more clearer.
我认为性能上的差异再明显不过了。