3 回答
TA贡献1900条经验 获得超5个赞
如果您只是锁定一个对象,我宁愿使用 synchronized
例:
Lock.acquire();
doSomethingNifty(); // Throws a NPE!
Lock.release(); // Oh noes, we never release the lock!
你必须明确地try{} finally{}到处做。
鉴于同步,它是非常明确的,不可能出错:
synchronized(myObject) {
doSomethingNifty();
}
也就是说,Lock对于那些你无法以如此干净的方式获取和释放的更复杂的东西,s可能更有用。老实说,我希望首先避免使用裸机,如果满足您的需求Lock,只需使用更复杂的并发控制,如a CyclicBarrier或a LinkedBlockingQueue。
我从来没有理由使用wait()或者notify()可能有一些好的。
TA贡献1946条经验 获得超3个赞
我想知道其中哪一个在实践中更好,为什么?
我发现Lock
和Condition
(以及其他新concurrent
类)只是工具箱的更多工具。我可以用我的旧羊角锤(synchronized
关键字)完成我需要的大部分工作,但在某些情况下使用它很尴尬。一旦我在工具箱中添加了更多工具,一些笨拙的情况变得更加简单:橡皮锤,圆头锤,撬棒和一些钉子。然而,我的旧羊角锤仍然看到它的使用份额。
我不认为一个人真的比另一个人“更好”,而是每个人都更适合不同的问题。简而言之,简单的模型和面向范围的性质synchronized
有助于保护我免受代码中的错误的影响,但是这些相同的优点有时会成为更复杂场景中的障碍。这些更复杂的场景是创建并发包以帮助解决的问题。但是使用这种更高级别的构造需要在代码中进行更明确和仔细的管理。
===
我认为JavaDoc中确实描述之间的区别的一个好工作Lock
和synchronized
(重点是我的):
锁实现提供了比使用同步方法和语句获得的更广泛的锁操作。它们允许更灵活的结构,可能具有完全不同的属性,并且可以支持多个关联的Condition对象。
...
使用同步方法或语句提供访问与每个对象相关联的隐式监视器锁,但是强制所有锁获取和释放在一个块结构的方式来发生:当多个锁被获取它们必须以相反的顺序被释放,并所有锁必须在获取它们的相同词法范围内释放。
虽然同步方法和语句的作用域机制使得使用监视器锁进行编程变得更加容易,并且有助于避免许多涉及锁的常见编程错误,但有时您需要以更灵活的方式使用锁。例如,* *用于遍历并发访问的数据结构的某些算法* 需要使用“hand-hand-hand”或“chain locking”:获取节点A的锁,然后获取节点B,然后释放A并获取C,然后释放B并获得D等等。所述的实施方式中锁定接口通过使得能够使用这样的技术允许获得并在不同的范围释放锁,并允许以任何顺序获取和释放多个锁。
随着这种增加的灵活性,附加责任。在不存在块结构锁定的去除锁的自动释放,与同步方法和语句发生。在大多数情况下,应使用以下习语:
...
当锁定和解锁发生在不同的范围内时,必须注意确保在保持锁定时执行的所有代码都受try-finally或try-catch保护,以确保在必要时释放锁定。
锁实现提供了使用同步方法和语句的附加功能,方法是提供获取锁(tryLock())的非阻塞尝试,获取可被中断的锁的尝试(lockInterruptibly(),以及尝试获取可以超时的锁(tryLock(long,TimeUnit))。
...
TA贡献1840条经验 获得超5个赞
您可以实现一切在公用事业java.util.concurrent中 做的低级原像synchronized
,volatile
或等待 / 通知
但是,并发性很棘手,并且大多数人至少会对其中的某些部分进行错误处理,从而导致其代码不正确或效率低下(或两者兼而有之)。
并发API提供了更高级别的方法,使用起来更容易(并且更安全)。简而言之,您不应再需要synchronized, volatile, wait, notify
直接使用了。
该锁 类本身就是对这个工具箱的下级侧,你甚至可能不会需要使用直接或者(你可以用Queues
和信号量和材料等,大部分的时间)。
添加回答
举报