为什么Java中的ArrayBlockingQueue使用锁和条件?

20 浏览
0 Comments

为什么Java中的ArrayBlockingQueue使用锁和条件?

java.util.concurrent API提供了一个名为Lock的类,它基本上会序列化控制以便访问关键资源。它提供了park()unpark()等方法。如果我们可以使用synchronized关键字和wait()notify()notifyAll()方法,我们也可以实现类似的功能。我想知道在实践中哪种方法更好,为什么?

0
0 Comments

为什么Java中的ArrayBlockingQueue使用锁和条件?原因是并发编程是棘手的,大多数人在某些方面都会出错,使得他们的代码要么不正确,要么低效(或两者兼有)。并发API提供了一种更高级的方法,更容易(因此更安全)使用。简而言之,你不应该再直接使用synchronized、volatile、wait和notify了。Lock类本身在这个工具箱中是较低级别的部分,你甚至不需要直接使用它(大多数情况下可以使用Queues和Semaphore等),plain old wait/notify被认为是低级别的原语,java.util.concurrent.locks.LockSupport的park/unpark也是。

解决方法是使用更高级别的工具,如Queues、Futures和CompletionService等。无法仅仅使用并发原语精确地复制AtomicXXX类的行为,因为它们依赖于在java.util.concurrent之前不可用的本地CAS调用。因此,使用锁和条件是为了更安全和更高效地实现并发编程。

0
0 Comments

为什么Java中的ArrayBlockingQueue使用锁和条件?

在Java中,synchronized关键字是保护共享资源的一种常用方式。然而,在某些复杂的情况下,synchronized关键字可能会变得笨拙。为了解决这些复杂情况,Java并发包提供了Lock和Condition等新的并发工具。Lock提供了比synchronized更丰富的锁定操作,它们允许更灵活的结构,具有不同的特性,并支持多个关联的Condition对象。

synchronized方法和语句的作用域机制使得使用监视器锁的编程更加容易,并有助于避免涉及锁的许多常见编程错误。然而,在某些情况下,需要以更灵活的方式处理锁。例如,并发访问数据结构的某些算法需要使用"hand-over-hand"或"chain locking"的技术:先获取节点A的锁,然后是节点B的锁,然后释放A并获取C的锁,然后释放B并获取D的锁,依此类推。Lock接口的实现允许在不同的作用域中获取和释放锁,并允许以任意顺序获取和释放多个锁。

然而,使用锁的灵活性也带来了额外的责任。与synchronized方法和语句不同,非块结构的锁定不会自动释放锁。所以在不同的作用域中进行锁定和解锁时,必须小心确保在持有锁的同时执行的所有代码都受try-finally或try-catch保护,以确保在必要时释放锁。

除了提供与synchronized方法和语句相比更多的锁定功能外,Lock实现还提供了一些额外的功能,如非阻塞尝试获取锁(tryLock())、可中断获取锁(lockInterruptibly())和可超时获取锁(tryLock(long, TimeUnit))。

因此,ArrayBlockingQueue在Java中使用锁和条件是为了提供更灵活、更丰富的锁定操作,并支持多个关联的条件对象。使用锁的灵活性使得在复杂的并发场景中更容易实现特定的算法和数据结构。

0
0 Comments

为什么Java中的ArrayBlockingQueue使用锁和条件?

0