Экземпляры класса, «владеющие» экземплярами TMultiReadExclusiveWriteSynchronizer? - PullRequest
3 голосов
/ 08 мая 2011

У меня есть многопоточная программа Delphi, создающая несколько экземпляров некоторых классов, и я хочу, чтобы у каждого экземпляра класса был свой экземпляр TMultiReadExclusiveWriteSynchronizer для использования в методах get и set определенных свойств.

например. Вот часть модуля, где я использую TMultiReadExclusiveWriteSynchronizer в одном классе:

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.

Проблема в том, что устройство создает один экземпляр TMultiReadExclusiveWriteSynchronizer, который затем используется несколькими экземплярами TSGThread.
Синхронизатор контролирует доступ только к приватному полю TSGThread.
Поток A может изменить поле в потоке B, используя открытое свойство, следовательно, необходим синхронизатор, но в каждом потоке должен быть отдельный синхронизатор, чтобы потокам не приходилось ждать друг друга, если они изменяют свои собственные свойства.

В справке Delphi говорится: «создать глобальный экземпляр TMultiReadExclusiveWriteSynchronizer», но обязательно ли для него всегда быть глобальным?
Если класс защищает доступ только к своим собственным свойствам, будет ли работать синхронизация с экземпляром TMultiReadExclusiveWriteSynchronizer в закрытом поле?

Ответы [ 3 ]

4 голосов
/ 08 мая 2011

Помощь говорит это:

Создайте глобальный экземпляр TMultiReadExclusiveWriteSynchronizer, связанный с глобальной памятью, которую вы хотите защитить.

Но у вас нет глобальной памяти. У вас есть память, специфичная для объекта потока, поэтому создайте объекты синхронизации для каждого объекта потока. Вы можете создать столько, сколько вам нужно. Создайте по одному для каждого общего элемента, к которому вы хотите получить индивидуальный доступ и защитить.

3 голосов
/ 08 мая 2011

Это немного не по теме, но в приведенном вами примере синхронизатор практически бесполезен. Логическое значение не может быть частично прочитано / записано при переключении контекста потока.

Кроме того, в вашем примере, код, подобный этому

sgThread.Waiting := not sgThread.Waiting;

может потерпеть неудачу.

Теперь вернемся к теме. Область действия TMultiReadExclusiveWriteSynchronizer должна быть такой же большой, как и ресурс, который она защищает. Поскольку вы хотите защитить приватное поле объекта, вы также можете объявить TMultiReadExclusiveWriteSynchronizer как приватное поле. (Вы защищаете доступ к приватному полю, а не доступ к собственности)

2 голосов
/ 08 мая 2011

Строго не обязательно, чтобы он был глобальным. необходимо для того, чтобы каждый доступ проходил через синхронизатор, чтобы обеспечить безопасность потока.Один из простых способов сделать это - сделать синхронизатор глобальной переменной, но есть и другие способы ее обработки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...