Domanda

In C #, il seguente codice (da questa pagina ) può essere utilizzato per pigramente istanziare una classe Singleton in un modo thread-safe:

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

Quale sarebbe il filo di codice Delphi sicura equivalente?


L'articolo cita anche due problemi con ricontrollato blocco in Java:

  • è possibile che il nuovo oggetto viene costruito prima si fa riferimento al punto helper il significato oggetto creato che due oggetti vengono creati
  • è possibile che si fa riferimento helper a punto in un blocco di memoria, mentre è ancora creato l'oggetto che significa che un riferimento a un oggetto incompleta verrà restituito

Così, mentre il codice del C # e la versione di Java nel look articolo citato quasi identiche, solo la versione C # funziona come previsto. Il che porta alla domanda supplementare se esistono anche questi due problemi in una versione di Delphi di interblocco ricontrollato?

È stato utile?

Soluzione

Usa System.TMonitor per bloccare l'istanza di oggetto in modo sicuro thread.

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;

Per ulteriori sguardo riferimento Blocco mio oggetto ..., per favore! Allen Bauer . In realtà, il rappresentante. Deduco da questo dovrebbe andare ad Allen.

Altri suggerimenti

Naturalmente, vale sempre la pena ricordare che doppio controllo è rotto . Questo problema risulta non da applicare al modello di memoria X 86, ma vale sempre la pena tenendo a mente per il futuro. Sono sicuro che ci sarà la versione di Delphi ad un certo punto che verrà eseguito su una piattaforma con un modello di memoria che è afflitto da questo problema.

Embarcadero hanno iniziato a utilizzare una versione senza blocchi di questo modello con interlocked confronto / scambio. Ad esempio:

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;

Mi rendo conto che questa non è una risposta alla domanda, ma non ha veramente in forma in un commento!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top