java.concurrent.ReentrantLock -为什么我们要多次获取相同的锁[重复]

vuv7lop3  于 2023-09-29  发布在  Java
关注(0)|答案(4)|浏览(78)

此问题已在此处有答案

Why use a ReentrantLock if one can use synchronized(this)?(8个回答)
10年前关闭。
我知道如果使用ReentrantLock,它允许同一个线程多次获取同一个锁。在内部,它有一个计数器来计算锁获取的次数。如果您两次获得相同的锁,则需要释放它两次。但我的问题是,为什么有人要多次获取锁,一次获取就足够了吗?谁能给予我一个常见的使用案例?

ee7vknir

ee7vknir1#

考虑下面的情况,在这种情况下,您需要一组不是原子的操作,而是原子的。例如,您可能希望设置数组的值,但在设置时返回其当前值。(为简洁起见,删除了try-finally)。

final ReentrantLock lock = new ReentrantLock();

final Object[] objects = new Object[10]
public Object setAndReturnPrevious(int index, Object val){
   lock.lock();
      Object prev = get(index);
      set(index,val);
      return prev;
   lock.unlock();
}
public void set(int index, Object val){
    lock.lock();
         objects[index] = val;
    lock.unlock();
}
public Object get(index index){...}

如果ReentrantLock不是可重入的,则会在set(index)处死锁

w80xi6nr

w80xi6nr2#

假设在一个类中有两个方法m1和m2,它们都是synchronized的,并且m2正在调用m1。在这种情况下,如果线程a已经在m1上获得了锁,并且不允许再次获得锁,则该阈值将继续等待调用m2(因为它已经获得了锁)。

gpfsuwkq

gpfsuwkq3#

考虑这个同步的例子。这同样适用于锁,但有更多的代码。

synchronized int getSum() {
     return getValue() + getOtherValue();
}

synchronized int getValue() {
     return value;
}

synchronized int getOtherValue() {
     return value;
}

避免可重入的唯一方法是创建每个方法的锁定和解锁版本。但是,如果你有两个示例A和B呢?A呼叫B,B呼叫A。B如何知道不调用A中的同步方法

vybvopom

vybvopom4#

有些人认为应该避免重入锁。在关键的部分,你应该确切地知道发生了什么。如果一个局部临界区调用了一个外部代码,而这个外部代码又调用了一个局部代码,这看起来相当复杂,而且有潜在的危险。最好有几个定义良好的临界区,只包含本地代码。

相关问题