什么是非阻塞并发,它与使用线程的普通并发有何不同。
非阻塞并发是协调线程之间的访问与阻塞并发的不同方法。有很多背景(理论)材料,但最简单的解释(似乎你正在寻找一个简单的,动手的答案),是非阻塞并发不使用锁。
我们为什么不在需要并发的所有方案中使用“非阻塞”并发。
我们做到了。我一会儿会告诉你。但是,对于每个并发问题,并不总是有高效的非阻塞算法。
“非阻塞”是否有任何开销
好吧,线程之间任何类型的共享信息都有开销,一直到CPU的结构,特别是当你得到我们所说的“争用”时,即同步多个试图同时写入同一内存位置的线程。但一般来说,在许多情况下,非阻塞比阻塞(基于锁的)并发更快,特别是所有给定算法/数据结构的众所周知的,简单,无锁实现的情况。Java提供的正是这些很好的解决方案。
我听说这在Java中可用。
绝对。对于初学者来说,java.util.concurrent.atomic 中的所有类都提供共享变量的免锁维护。此外,java.util.concurrent 中名称以 ConcurrentLinked 或 ConcurrentSkipList 开头的所有类都提供了列表、映射和集合的无锁实现。
是否有任何特定的场景我们应该使用此功能。
您可能希望在原本(在 JDK 1.5 之前)使用 Collections.synchronizedlist 的所有情况下使用无锁队列和 deque,因为它们在大多数情况下都能提供更好的性能。也就是说,每当多个线程同时修改集合时,或者当一个线程正在修改集合而其他线程正在尝试读取它时,您都可以使用它们。请注意,非常流行的 ConcurrentHashMap 实际上在内部使用锁,但它比 ConcurrentSkipListMap 更受欢迎,因为我认为它在大多数情况下提供了更好的性能。但是,我认为Java 8将包括ConcurrentHashMap的无锁实现。
将这些方法之一用于集合是否有区别/优势?权衡取舍
好吧,在这个简短的例子中,它们是完全相同的。但请注意,当您具有并发读取器和写入器时,必须同步读取和写入,而 Collections.synchronizedList() 可以做到这一点。您可能希望尝试使用无锁 ConcurrentLinkedQueue 作为替代方法。在某些情况下,它可能会为您提供更好的性能。
一般说明
虽然并发性是一个非常重要的学习主题,但请记住,它也是一个非常棘手的主题,即使是非常有经验的开发人员也经常犯错。更糟糕的是,您可能仅在系统负载过重时才发现并发错误。因此,我总是建议使用尽可能多的现成并发类和库,而不是推出自己的并发类和库。