我有一个java类,它接收来自外部的输入(即同时运行的许多线程),然后将输入存储到两个循环缓冲区中。这些缓冲区协同工作以执行相同的工作,并且仅根据其优先级而不同。也就是说,缓冲区被命名为“primary”和“secondary”:当输入到达时,首先检查主缓冲区,如果它已满,则检查辅助缓冲区。即使辅助缓冲区已满,输入也会等待其中一个缓冲区中的插槽可用。我认为我可以通过首先锁定主缓冲区上的访问权限来管理并发性,并且仅在必要时请求锁定辅助缓冲区,同时仍然保持先前的锁定。我不知道为什么,但对我来说听起来很奇怪。只要它不会导致死锁或繁重的饥饿场景,同时持有两个锁是好的/安全的实践吗?
感谢您的关注。
如果您不能保证始终以相同的顺序获取两个锁,则存在死锁的风险。 如果您可以保证在进入内锁时始终保持外锁,则内锁是多余的。 (*) 如果你可以保证,如果代码持有内部锁,没有其他代码会请求外部锁,那么这不会导致死锁。但是,这很脆弱,因为现在你在推理通常相当远的代码。除非存在外部锁定以确保不同时获取外部锁定,否则您将回到上述两种情况之一。
所以是的,你应该避免嵌套锁:你要么死锁,要么没用,或者你有一个脆弱的系统。
(*)这里有一个例外:如果外部锁定代码区域启动使用内部锁定坐标的线程,则不适用。 这种代码是非常罕见的,与你在实践中看到的嵌套锁方案有很大不同,我甚至不愿意将它称为嵌套锁,即使它是技术上的。