java.concurrent.ReentrantLock - why we want to acquire the same lock multiple times [duplicate]
Asked Answered
Z

4

9

I know if using ReentrantLock, it allows the same thread to acquire the same lock more than once. Internally, it has a counter to count the number of the lock acquisition. If you acquired the same lock twice, you would need to release it twice. But my question is that why would someone want to acquire the lock multiple times, should one time acquisition be enough? Can someone give me a common use case?

Zimmer answered 3/9, 2013 at 15:30 Comment(2)
This kind of thing happens a lot with file access with read/writingGerick
http://en.wikipedia.org/wiki/Semaphore_(programming) There are some good analogies here.Gerick
A
17

Consider the following case in which you need a set of operations which isn't atomic, be atomic. For example you may want to set a value of an array but return its current value upon setting. (try-finally removed for brevity).

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){...}

If ReentrantLock wasn't reentrant you would deadlock at set(index)

Axilla answered 3/9, 2013 at 15:38 Comment(4)
it makes sense now, this differentiate ReentrantLock to synchronized(this), right? in this case, sychronized(this) would deadlock at get(index).Zimmer
@Zimmer Actually synchronized is also reentrant so in neither case would you dead lock.Axilla
@John Vint wouldn't you deadlock on set (where you would indefinitely wait for the release of the lock that you hold) rather than get ?Obcordate
Yes, @user3529850, you're absolutely right. Must have been a typo long ago.Axilla
P
7

Suppose in a class you have two methods m1 and m2, both synchronized and m2 is calling m1. In that case if thread a has taken a lock on m1 and taking a lock again is not allowed then that thresad will keep on waiting for calling m2 (as it already has a the lock)

Paba answered 3/9, 2013 at 15:33 Comment(0)
T
3

Consider this synchronized example. The same applies to lock but with more code.

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

synchronized int getValue() {
     return value;
}

synchronized int getOtherValue() {
     return value;
}

The only way to avoid being re-entrant is to create locked and unlocked versions of each method. However what if you have two instances A and B. A calls B which calls A. How does B know not to call a synchronized method in A.

Throat answered 3/9, 2013 at 15:54 Comment(0)
C
1

Some argue that reentrant locking should be avoided. In a critical section, you should know exactly what is going on. If a local critical section may call a foreign code that may call a local code back, that seems pretty complicated and potentially dangerous. It is better to have just a few well defined critical sections containing only local code.

Cannibal answered 3/9, 2013 at 16:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.