Frage

In C #, der folgende Code (von dieser Seite) können zu träge verwendet werden instantiate eine Singleton-Klasse in einem Thread sichere Art und Weise:

  class Foo {
        private volatile Helper helper = null;
        public Helper getHelper() {
            if (helper == null) {
                lock(this) {
                    if (helper == null)
                        helper = new Helper();
                }
            }
            return helper;
        }
    }

Was der äquivalent Thread-sicher Delphi-Code wäre?


Der Artikel erwähnt auch zwei Probleme mit doppelt geprüft Locking in Java:

  • ist es möglich, dass das neue Objekt aufgebaut wird, bevor der Helfer Bezug auf Punkt, an der neu erstellten Objekt Bedeutung gemacht wird, dass zwei Objekte erzeugt
  • ist es möglich, dass der Helfer Bezug auf Punkt auf einem Speicherblock gemacht wird, während das Objekt noch erstellt wird was bedeutet, dass ein Verweis auf ein unvollständiges Objekt wird zurückgegeben

So, während der Code der C # und die Java-Version in dem erwähnten Artikel Blick fast identisch, nur die C # -Version funktioniert wie erwartet. Das führt zu der zusätzlichen Frage, ob diese beiden auch Probleme in einer Delphi-Version von Double-Checked Locking existieren?

War es hilfreich?

Lösung

Verwenden System.TMonitor die Objektinstanz in einem Thread sichere Art und Weise zu sperren.

function TFoo.GetHelper(): THelper;
begin
  if not Assigned(FHelper) then
  begin
    System.MonitorEnter(Self);
    try
      if not Assigned(FHelper) then
        FHelper := THelper.Create();
    finally
      System.MonitorExit(Self);
    end;
  end;
  Result := FHelper;
end;

Für weitere Referenz Blick auf sperren mein Objekt ..., bitte! von Aller Bauer . In der Tat, die rep. Ich entnehme dies sollte zu Allen gehen.

Andere Tipps

Natürlich ist es immer zu bedenken, dass doppelt geprüft Locking ist Gebrochene . Dieses Problem stellt sich heraus, nicht auf das x86-Speichermodell anzuwenden, aber es ist immer zu bedenken, für die Zukunft. Ich bin sicher, es wird Delphi-Version an einem gewissen Punkt, die auf einer Plattform mit einem Speichermodell ausgeführt werden, die von diesem Problem betroffen ist.

Embarcadero hat mit einer Lock-freier Version dieses Musters mit verzahnte vergleichen / Austausch gestartet. Zum Beispiel:

class function TEncoding.GetUnicode: TEncoding;
var
  LEncoding: TEncoding;
begin
  if FUnicodeEncoding = nil then
  begin
    LEncoding := TUnicodeEncoding.Create;
    if InterlockedCompareExchangePointer(Pointer(FUnicodeEncoding), LEncoding, nil) <> nil then
      LEncoding.Free;
  end;
  Result := FUnicodeEncoding;
end;

Ich weiß, dies auf die Frage keine Antwort, aber es nicht wirklich in einem Kommentar passen!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top