我正在修改一些非常复杂的代码,我需要在此基础上添加自己的同步。
但是,现有代码有大约十几个(如果不是更多)不同的锁,我的代码需要调用它的一些方法。 我真的不知道获取锁的顺序,我也无法真正控制它。
所以,我的问题是,如果我用一个锁替换所有不同的锁,会发生什么?。除了牺牲粒度,还有其他问题我应该注意吗?
谢谢!
I'm modifying a bit of seriously complex code and I need to add my own synchronization on top of this.
However, the existing code has about a dozen, if not more, different locks, and my code needs to call some of its methods. I don't really know the order in which the locks are being obtained, nor can I really control it.
So, my question is, what would happen if I replaced all the different locks by a single lock?.Apart from sacrificing granularity, is there any other issue I should be aware of?
Thanks!
最满意答案
如果您更改了所有synchronized块(和方法) 以及所有其他阻塞结构,我认为您应该没问题 - 最坏的情况是,您的应用程序退化为执行串行连接。 但是,如果你只更改其中一些,你可能会陷入僵局。 考虑两个线程各自获取多个锁的情况:
Thread 1: synchronized A synchronized B Thread 2: synchronized B synchronized C这里没有死锁的风险,但如果用新的普通锁替换A和C (但不是B ),那么你将拥有:
Thread 1: synchronized L synchronized B Thread 2: synchronized B synchronized L......这是典型的死锁案例。
考虑另一个场景,其中锁本身不提供死锁,而是像CountDownLatch一样死锁一个阻塞类:
Thread 1: synchronized A latch L.countDown() Thread 2: synchronized B latch L.await()在这种情况下,更改两个synchronized块以锁定公共锁定不会导致它们之间的死锁,但如果线程2首先获得锁定将导致死锁:它将等待锁存器的countDown,这将永远不会到来,因为线程1是在synchronized入口点被阻止。 此示例也适用于其他阻塞结构:信号量,阻塞队列等。
If you change all of the synchronized blocks (and methods), and all the other blocking structures, I think you should be fine -- worst case, your app degenerates to having serial execution. But if you only change some of them, you could get deadlock. Consider a scenario where two threads are each acquiring multiple locks:
Thread 1: synchronized A synchronized B Thread 2: synchronized B synchronized CThere's no risk of deadlock here, but if you replace A and C (but not B) with the new, common lock, then you'll have:
Thread 1: synchronized L synchronized B Thread 2: synchronized B synchronized L... which is the classic deadlock case.
Consider another scenario, where the locks don't provide deadlock themselves, but instead deadlock a blocking class like a CountDownLatch:
Thread 1: synchronized A latch L.countDown() Thread 2: synchronized B latch L.await()In this case, changing both synchronized blocks to lock on a common lock won't cause deadlock between them, but will cause deadlock if thread 2 gets the lock first: it'll await the latch's countDown, which will never come because thread 1 is blocked at its synchronized entry point. This example applies to other blocking structures, too: semaphores, blocking queues, etc.
更多推荐
发布评论