I have a multi-threaded Delphi program creating multiple instance of some classes, and I want each class instance to have its own instance of TMultiReadExclusiveWriteSynchronizer for use in the get and set methods of specific properties.
E.g. Here’s part of a unit where I’m using a TMultiReadExclusiveWriteSynchronizer in one class:
interface
TSGThread=class(TThread)
private
fWaiting:boolean;
function getWaiting:boolean;
procedure setWaiting(value:boolean);
public
property waiting:boolean read getWaiting write setWaiting;
end;
implementation
var syncWaiting:TMultiReadExclusiveWriteSynchronizer;
function TSGThread.getWaiting:boolean;
begin
syncWaiting.BeginRead;
result:=fWaiting;
syncWaiting.EndRead;
end;
procedure TSGThread.setWaiting(value:boolean);
begin
syncWaiting.BeginWrite;
fWaiting:=value;
syncWaiting.EndWrite;
end;
initialization
syncWaiting:=TMultiReadExclusiveWriteSynchronizer.Create;
finalization
syncWaiting.Free;
end.
The problem with this is that the unit creates one instance of TMultiReadExclusiveWriteSynchronizer which is then used by multiple instances of TSGThread.
The synchronizer is only controlling access to a private field of TSGThread.
Thread A could modify the field in Thread B using the public property, hence the need for the synchronizer, but there should be a separate synchronizer in each thread so the threads don’t have to wait on each other if they’re modifying their own properties.
Delphi Help says “create a global instance of TMultiReadExclusiveWriteSynchronizer”, but is it strictly necessary for it to always be global?
If a class is only protecting access to its own properties, will the synchronization work with a TMultiReadExclusiveWriteSynchronizer instance in a private field?
It’s not strictly necessary for it to be global. It is necessary for the every access to go through the synchronizer in order to maintain thread safety. One easy way to enable that is by making the synchronizer a global variable, but there are other ways to handle it.