java - 如何在Java中原子地获取多个锁?

标签 java

Java 中获取多个锁的常见模式如下:

synchronized (lock1) {
...
   synchronized(lock2) {
   }
}

这是死锁的常见原因,因为如果另一个线程的顺序相反,即:

synchronized (lock2) {
...
   synchronized(lock1) {
   }
}

那么没有线程能够继续进行。两者都被无限期阻止。

C++ 提供了 scoped_lock构造以原子方式获取多个锁:

When a scoped_lock object is created, it attempts to take ownership of the mutexes it is given. When control leaves the scope in which the scoped_lock object was created, the scoped_lock is destructed and the mutexes are released. If several mutexes are given, deadlock avoidance algorithm is used as if by std::lock.

Java有这样的东西吗?

最佳答案

Does Java have such a thing?

你不能使用 Java 原始互斥体来做到这一点;即同步。 但是,如果您使用 Lock 对象而不是原始互斥体,则可以使用 Lock.tryLock 实现这种行为。例如。

Lock lock1 ...
Lock lock2 ...

lock1.lock();  // This blocks until the lock is acquired
try {
    if (lock2.tryLock()) {  // NB: this does not block ... so no deadlock
       try {
          // Do stuff
       } finally {
          lock2.unlock();
       } 
    } else {
       System.out.println("Potential deadlock avoided!");
    }
} finally {
    lock1.unlock();
} 

请注意,为此您必须使用try ...finally。由于不能自动关闭,尝试使用资源不会释放锁。

更多详情,请参阅javadocs对于Lock接口(interface)。


值得注意的是,虽然上述不会死锁,但仍然存在(理论上)活锁的风险,即两个线程循环上述代码并反复避免死锁......但没有取得实际进展。

正如评论者所指出的,避免死锁的另一种方法是设计应用程序,以便始终以相同的顺序获取锁对。

关于java - 如何在Java中原子地获取多个锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77026683/

相关文章:

java - 无法使用 liquibase 独立 shell 脚本

java - 一个maven的artifactID可以引用多个文件吗?

java - 为什么通过刷新 token 获取 Azure AD token 没有签名算法?

java - 使用 DAO 类时出现 NullPointerException

java - 无法在 Spring MVC 中发送 POST 请求

java - 如何禁用双向关联的 Hibernate 外键约束?

java - 用户编写的程序如何发送到图书馆?

java - 我可以使用 Java API 将图像文件存储在 firebase 中吗

java - 对字符串数组进行排序会出现 NullPointerException

java - 相机位图/图像保存后加载滑动层