Einzelnen Beitrag anzeigen

Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.840 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

Re: TMultiReadExclusiveWriteSynchronizer mit Speicher verknü

  Alt 31. Aug 2005, 14:01
der_boss schrieb in einer PN
"Um einen globalen Speicherbereich auf diese Weise zu schützen, erzeugen Sie eine globale Instanz von TMultiReadExclusiveWriteSynchronizer und verknüpfen diese mit dem betreffenden Speicher. "

Hallo MaBuSE,

ich hab gesehen, dass du dich schon einmal mit dem TMultiReadExclusiveWriteSynchronizer auseinander gesetzt hast. man soll da Speicherbereich verknüpfen, aber wie geht das?

Danke!!


Das ist eigentlich reativ einfach (und selbsterklärend):
Das beispiel ist vom Verwendungszweck ehr sinnfrei ,
aber es gibt 2 TMultiReadExclusiveWriteSynchronizer Objekte, die mit "Bereich 1" und "Bereich 2" "verknüpft" sind.

Es werden mehrere paralele Lesezugriffe von Threads in die Bereiche zugelassen, aber beim Schreiben müssen alle Lesenden (und schreibenden) Threads warten bis EndWrite aufgerufen wurde.

Delphi-Quellcode:
unit Unit2;

interface

uses
  Classes, SysUtils;

type
  TBeispLockThread = class(TThread)
  private
    { Private-Deklarationen }
    Text1,
    Text2: string;
    i: LongInt;
    procedure UpdateCaption;
  protected
    procedure Execute; override;
  end;

implementation

uses
  Unit1; // mit TForm1

var
  Lock1 : TMultiReadExclusiveWriteSynchronizer;
  Lock2 : TMultiReadExclusiveWriteSynchronizer;

{ Wichtig: Methoden und Eigenschaften von Objekten in visuellen Komponenten dürfen
  nur in einer Methode namens Synchronize aufgerufen werden, z.B.

      Synchronize(UpdateCaption);

  und UpdateCaption könnte folgendermaßen aussehen:

    procedure TBeispLockThread.UpdateCaption;
    begin
      Form1.Caption := 'Aktualisiert in einem Thread';
    end; }


{ TBeispLockThread }

procedure TBeispLockThread.Execute;
var
  j: Integer;
begin
  { Thread-Code hier einfügen }

  while i < 100000 do
  begin
    // i ausgeben
    Synchronize(UpdateCaption);

    // hier wird im Bereich 1 geschrieben
    Lock1.BeginWrite;
    Text1 := 'Bla Bla';
    Lock1.EndWrite;

    // hier wird im Bereich 2 geschrieben
    Lock2.BeginWrite;
    Text2 := 'noch mehr Bla Bla';
    Lock2.EndWrite;

    For j := 0 to Random(100) do
    begin
      // hier wird im Bereich 1 gelesen
      Lock1.BeginRead;
      i := i + Length(Text1);
      Lock1.EndRead;
    end;

    // i ausgeben
    Synchronize(UpdateCaption);
    For j := 0 to Random(100) do
    begin
      // hier wird im Bereich 2 gelesen
      Lock2.BeginRead;
      i := i + Length(Text2);
      Lock2.EndRead;
    end;
  end;

  // i ausgeben
  Synchronize(UpdateCaption);
end;


procedure TBeispLockThread.UpdateCaption;
begin
  Form1.Caption := 'i := ' + IntToStr(i);
end;

initialization
  Lock1 := TMultiReadExclusiveWriteSynchronizer.Create;
  Lock2 := TMultiReadExclusiveWriteSynchronizer.Create;
finalization
  Lock1.Free;
  Lock2.Free;
end.
In der SysUtils steht:
{ TMultiReadExclusiveWriteSynchronizer minimizes thread serialization to gain
read access to a resource shared among threads while still providing complete
exclusivity to callers needing write access to the shared resource.
(multithread shared reads, single thread exclusive write)
Read locks are allowed while owning a write lock.
Read locks can be promoted to write locks within the same thread.
(BeginRead, BeginWrite, EndWrite, EndRead)

Note: Other threads have an opportunity to modify the protected resource
when you call BeginWrite before you are granted the write lock, even
if you already have a read lock open. Best policy is not to retain
any info about the protected resource (such as count or size) across a
write lock. Always reacquire samples of the protected resource after
acquiring or releasing a write lock.

The function result of BeginWrite indicates whether another thread got
the write lock while the current thread was waiting for the write lock.
Return value of True means that the write lock was acquired without
any intervening modifications by other threads. Return value of False
means another thread got the write lock while you were waiting, so the
resource protected by the MREWS object should be considered modified.
Any samples of the protected resource should be discarded.

In general, it's better to just always reacquire samples of the protected
resource after obtaining a write lock. The boolean result of BeginWrite
and the RevisionLevel property help cases where reacquiring the samples
is computationally expensive or time consuming.

RevisionLevel changes each time a write lock is granted. You can test
RevisionLevel for equality with a previously sampled value of the property
to determine if a write lock has been granted, implying that the protected
resource may be changed from its state when the original RevisionLevel
value was sampled. Do not rely on the sequentiality of the current
RevisionLevel implementation (it will wrap around to zero when it tops out).
Do not perform greater than / less than comparisons on RevisionLevel values.
RevisionLevel indicates only the stability of the protected resource since
your original sample. It should not be used to calculate how many
revisions have been made.
}



Ich hoffe das hilft Dir.
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat