2010-04-08 10 views
7

Como he sabido, hay dos tipos comunes de las prácticas para garantizar la seguridad de los subprocesos de lazy-inicialización:¿Es posible o razonable implementar el bloqueo con doble verificación en Delphi?

  1. bloqueo doble comprobación (Marca la variable como volátil para evitar el ordenamiento de memoria)
  2. InterlockedCompareExchangePointer

Parece que VCL utiliza la segunda práctica. ¿Hay alguna razón?

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

o hay ningún método mejor?

Gracias!

Respuesta

4

No debería haber mucha diferencia de velocidad. En ambos enfoques, el campo global se verifica primero si se inicializa y la inicialización se realiza solo cuando es necesario. Por lo tanto, la mayoría de las veces la función simplemente lo comparará, saltará, moverá, sin ninguna inicialización.

Cuando se realiza la inicialización, InterlockedCompareEtc tiene dos ventajas sobre el bloqueo.

  1. Es más rápido.
  2. El código es más corto (no es necesario inicializar un bloqueo, etc.).

Encuentro el enfoque InterlockedCompareEtc "más limpio" y lo uso en mi código. Pero el bloqueo funcionaría igual de bien.

+0

No me gusta la duplicación de código, así que me dieron algunas ideas que pueden simplificar el código anterior: 1. Cuando el tipo de parámetro "T" tiene el constructor por defecto Resultado: = TUtils.GetInstance (FUTF8Encoding, TUTF8Encoding); 2. Use un método anónimo para crear una instancia local. Resultado: = TUtils.GetInstance (FUTF8Encoding, función: TEncoding comienzan Resultado: = TUTF8Encoding.Create; final); ¿Qué tal eso? –

+0

Debe editar su publicación original, Paul, en lugar de escribir el comentario. – gabr

Cuestiones relacionadas