Class instances "owning" TMultiReadExclusiveWriteSynchronizer instances?
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 pr开发者_开发问答ivate 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?The help says this:
Create a global instance of
TMultiReadExclusiveWriteSynchronizer
that is associated with the global memory you want to protect.
But you don't have global memory. You have thread-object-specific memory, so create synchronization objects for each thread object. You can create as many as you need. Create one for each shared element you wish to individually access and protect.
This is a little bit off-topic, but in the example you give, the synchronizer is pretty much useless. A boolean cannot be partially read/written on a thread context switch.
Also, with your example, code like this
sgThread.Waiting := not sgThread.Waiting;
could fail.
Now, back to the topic. TMultiReadExclusiveWriteSynchronizer's scope needs to be as large as the resource it protects. Since you want to protect a private field of an object, you can declare the TMultiReadExclusiveWriteSynchronizer as a private field as well. (You are protecting access to the private field, not the access to the property)
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.
精彩评论