Pregunta

En C #, el siguiente código (de esta página ) se puede utilizar para perezosamente instanciar una clase singleton de una manera segura hilo:

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

¿Cuál sería el código de Delphi hilo de seguridad equivalente?


El artículo también menciona dos problemas con una doble comprobación de bloqueo en Java:

  • es posible que el nuevo objeto se construye antes de que se hizo la referencia ayudante para punto en el significado objeto recién creado que dos objetos son creados
  • es posible que se hace la referencia ayudante para punto en un bloque de memoria mientras que todavía se está creando el objeto lo que significa que será devuelto una referencia a un objeto incompleto

Así, mientras que el código de la C # y la versión de Java en el artículo mencionado aspecto casi idéntico, sólo la versión de las obras de C # como se esperaba. Lo que lleva a la pregunta adicional si también existen estos dos problemas en una versión de Delphi sometido a control de bloqueo doble?

¿Fue útil?

Solución

Uso System.TMonitor para bloquear la instancia de objeto de una manera segura hilo.

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;

Para más mirada referencia en Lock mi objetivo ..., por favor! de Allen Bauer . De hecho, el representante. Deduzco de esto debe ir a Allen.

Otros consejos

Por supuesto, siempre es bueno recordar que es roto. Este problema resulta no aplicar al modelo de memoria x86 pero siempre es importante tener en cuenta para el futuro. Estoy seguro de que habrá versión de Delphi en algún momento que se ejecutará en una plataforma con un modelo de memoria que está afectado por este problema.

Embarcadero han empezado a utilizar una versión libre de la cerradura de este patrón con / intercambio comparar entrelazada. Por ejemplo:

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;

Me doy cuenta de que esto no es una respuesta a la pregunta pero no encajaba realmente en un comentario!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top