Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why only one upgradable lock can be held with shared locks

The boost documentation for upgradable and shared locks says that when shared locks are held only one other thread may acquire an upgradable lock. So that if other threads try to acquire an upgradable lock when shared lock(s) are held along with the upgradable lock they will block.

Is there some deadlock possibility that I am missing when more than one thread acquire upgradable locks along with one (or more than one shared lock)? Or is this just a logical requirement (so a "should not do this" sort of thing)?

Note that I am not talking about exclusively locked states. Only an upgradeable locked state. If an upgradable lock is held along with other shared locks it is in essence a READ lock. Then why can't two upgradable locks be held together?

like image 491
Curious Avatar asked Jul 29 '16 04:07

Curious


People also ask

What is the difference between shared locks and exclusive locks?

The two types are exclusive and shared locks. Exclusive locks can be active or retained; shared locks can only be active (see Active and retained states for locks ).

What does shared lock mean?

When a statement reads data without making any modifications, its transaction obtains a shared lock on the data. Another transaction that tries to read the same data is permitted to read, but a transaction that tries to update the data will be prevented from doing so until the shared lock is released.

What do you mean by exclusive lock?

When a statement modifies data, its transaction holds an exclusive lock on data that prevents other transactions from accessing the data. This lock remains in place until the transaction holding the lock issues a commit or rollback.


1 Answers

Is there some deadlock possibility that I am missing when more than one thread acquire upgradable locks

TL;DR Yes, there is.

along with one (or more than one shared lock)

This doesn't really affect the deadlock possibility. Allowing shared locks while upgradeable lock exists is simply a feature of upgradeable locks, compared to an exclusive lock.


Let us first consider what upgradeable locks can be used for. We shall imagine the following situation:

  • Several writer threads must check a condition (a read operation), then depending on that, modify the state
  • Checking the condition is expensive
  • The condition is satisfied rarely.
  • Other threads also read the state.

Now, let us consider that we only have reader (shared) / writer (exclusive) locks, with no upgradeable lock:

  1. Writer takes an exclusive lock, and starts checking the condition
  2. Other threads must block while the expensive check operation is running - even if they only need to read.

It may be considered a disadvantage that the read portion of the check - write cycle blocks even reading threads. So, let us consider an alternative:

  1. Writer takes a shared lock, and starts checking the condition
  2. Other threads may also take shared locks
  3. Writer has checked the condition, and releases the read lock
  4. The condition was satisfied, and writer now tries to take an exclusive lock to proceed

Between 3. and 4. more than one writer may have finished checking the state - since they can check concurrently - and are now racing to take the exclusive lock. Only one can win, and others must block. While they are blocking, the winner is modifying the state.

In this situation, the writers waiting to grab the exclusive lock can not assume that the condition that they checked is valid any more! Another writer may have grabbed the lock before them, and the state has now been modified. They could ignore this, which might lead to undefined behaviour, depending on what the relation with the condition and the modification is. Or, they could check the condition again when they get the exclusive lock, which reverts us back to the first approach, except with potentially redundant checks that were useless because of the race. Either way, this approach is worse than the first one.


A solution for the situation above is the privileged read (upgradeable) lock:

  1. Writer takes a privileged lock, and starts checking the condition
  2. Other threads may take shared locks
  3. Writer has checked the condition which was satisfied, and upgrades to exclusive lock (must block until other locks have been released)

Let us consider a situation where multiple writers have been granted a privileged lock. They get to check the expensive condition concurrently, which is nice, but they still have a race to upgrade the lock. This time, the race results in a dead lock, because each writer hold the read lock, and wait for all read locks to be released before they can upgrade.

If the upgradeable lock is exclusive in relation to other upgradeable locks, then this dead lock cannot occur, and the race doesn't exist between the expensive check and the modification, but reader threads may still operate while the writer is checking.

like image 86
eerorika Avatar answered Oct 16 '22 12:10

eerorika