|
Reported by Anders Melander
It is currently impossible to use the lock promotion feature of
TMultiReadExclusiveWriteSynchronizer without serious risk
of dead-locks. Even though the help does not say so, a comment
in the source code states that "Read locks can be
promoted to write locks".
Consider the following (pseudo) code:
var
FSynchronizer: TMultiReadExclusiveWriteSynchronizer;
...
begin
// Aquire read lock
FSynchronizer.BeginRead;
try
while (...scan list for resource...) do
if (...resource found...) then
begin
// Promote read lock to write lock
FSynchronizer.BeginWrite;
try
...do something to resource...
finally
FSynchronizer.EndWrite;
end;
end;
finally
FSynchronizer.EndRead;
end;
end;
If two threads are running this code concurrently, a dead-lock will occur if both threads
attempt to promote their read lock to a write lock.
- Thread A calls BeginRead to aquire read lock.
- Thread B calls BeginRead to aquire read lock.
- Thread A calls BeginWrite to promote read lock to write lock.
The call blocks because another thread has already aquired a read lock.
- Thread B calls BeginWrite to promote read lock to write lock.
The call blocks because another thread has already aquired a read lock.
- Dead-lock.
Thread A is waiting for thread B and thread B is waiting for thread A.
The bug in TMultiReadExclusiveWriteSynchronizer is not that a dead-lock can occur, but
the fact that the dead-lock isn't detected. The scenario described above will always
cause dead-locks no matter how TMultiReadExclusiveWriteSynchronizer is implemented, but
it should detect the dead-lock and raise an exception.
Also, since most people are unaware of the dead-lock risk of lock promotion, this problem
should be documented in the online help. |