P-P
P-P

Reputation: 1700

Would you explain lock ordering?

I learned that I should unlock reverse order to lock order. For example.

A.lock();
B.lock();
B.unlock();
A.unlock();

But, what happen if I did like this :

A.lock();
B.lock();
A.unlock();
B.unlock();

I try to make a deadlock scenario, but if I always lock A earlier then B, then I don't know how deadlock would happen. Would you help me?

Upvotes: 40

Views: 32040

Answers (7)

Frank Wang
Frank Wang

Reputation: 920

      > lock(B)                                                                                                                                                                                                 
      >  ----------    lock(C)
      >  ----------    lock(B)    >>>> would block here 
      >  ----------    release(B)
      >  ----------    release(C)
      > lock(C)       >>>>>> would block here 
      > release(B)
      > release(C)

Their answer is great, here is another situation a deadlock may occur if unordered lock & release is performed. One word, Unordered release & lock break the assumption which we used to design our shared resource management and critical zone.

Upvotes: 0

Jingguo Yao
Jingguo Yao

Reputation: 7986

And for Java, unlocking is in the reverse order if synchronized keyword is used for locking. There is no way to unlock in a different order for using synchronized keyword.

synchronized(a) {
  synchronized(b) {
    // statements
  }
}

Upvotes: 0

Adrian McCarthy
Adrian McCarthy

Reputation: 47954

In the simple case given, unlocking in the reverse order is not necessary to avoid a deadlock.

However, as the code gets more complicated, unlocking in the reverse order helps you maintain proper lock ordering.

Consider:

A.lock();
B.lock();
Foo();
A.unlock();
Bar();
B.unlock();

If Bar() attempts to reacquire A, you've effectively broken your lock ordering. You're holding B and then trying to get A. Now it can deadlock.

If you unlock in the reverse order style (which is very natural if you use RAII):

A.lock();
B.lock();
Foo();
B.unlock();
Bar();
A.unlock();

then it doesn't matter if Bar() attempts to take a lock, as lock ordering will be preserved.

Upvotes: 71

Thilo
Thilo

Reputation: 262474

Lock ordering just means that you prevent deadlocks by obtaining locks in a fixed order, and do not obtain locks again after you start unlocking.

I do not think the order of unlocks makes any difference here (in fact, it should be beneficial to release a lock as soon as possible, even if out of order)

Upvotes: 32

djna
djna

Reputation: 55897

The order of unlock will not affect how prone your system is to deadlock, however there's one reasons to think about the order of unlock:

In order to avoid deadlocks you must make sure that your lock/unlocks are paired, in that you never miss an unlock. As a stylistic approach, by conspicuosly having blocks of code that are responsible for a particualr lock it's much easier to visually identifiy that locks and unlocks are paired. The end-effect is that clearly correct code will probably take and release the locks as you describe.

Upvotes: 2

ironic
ironic

Reputation: 8939

I do not think deadlock would happen here. The general deadlock concept is one thread waits for some resource locked by other thread, while other thread needs resource locked by first thread to finish and release resource needed by first.

Further reading

Upvotes: 2

Don Neufeld
Don Neufeld

Reputation: 23218

Your example isn't going to deadlock with itself ever. Unlocking in reverse order isn't important, it's locking in a consistent order. This will dead lock, even though unlocks are in reverse order

Thread 1

A.lock();
B.lock();
B.unlock();
A.unlock();

Thread 2

B.lock();
A.lock();
A.unlock();
B.unlock();

Upvotes: 14

Related Questions