Primoz Gabrijelcic [1] recently reported a possible bug with TMonitor [2], in the more advanced side of TMonitor.
However, when experimenting with it for DWS, I bumped on issues in the basic usage scenarios too, and reverted to using critical sections. It seems that as of Delphi XE, short of a patch, TMonitor is just a waste of 4 bytes per object instance.
One of the basic usage of TMonitor I’m referring to would be to replace a critical section:
TMonitor.Enter(someObject); try // protected code finally TMonitor.Exit(someObject); end;
However, TMonitor is having a problem with the above, and you can quickly run into situations where everything gets serialized, even when there is no need to. Let’s look at a minimal thread:
type TMyThread = class(TThread) Count : Integer; Obj : TObject; procedure Execute; override; end; procedure TMyThread.Execute; begin while not Terminated do begin System.TMonitor.Enter(Obj); try Dec(Count); // or do something else if Count<=0 then Break; finally System.TMonitor.Exit(Obj); end; end; end;
Assuming you create two instances of the above thread class, which are working on two different “Obj” instances, the two threads should be able to run in parallel, as they don’t operate on the same memory structures at all, right?
Well, if you use plain old critical sections, they will, but if you use TMonitor like in the above code, they won’t, they’ll just run serialized, and all but the first thread will suffer from severe contention, which hints that a race condition [3] is hiding somewhere in TMonitor’s code…