2009-09-07 11 views
8

Me pregunto si este código que un desarrollador compañero (que se ha ido) está bien, creo que quería evitar poner un candado. ¿Hay una diferencia de rendimiento entre esto y solo usar un bloqueo directo?Interbloqueado utilizado para incrementar/imitar un booleano, ¿es esto seguro?

private long m_LayoutSuspended = 0; 
    public void SuspendLayout() 
    { 
     Interlocked.Exchange(ref m_LayoutSuspended, 1); 
    } 

    public void ResumeLayout() 
    { 
     Interlocked.Exchange(ref m_LayoutSuspended, 0); 
    } 

    public bool IsLayoutSuspended 
    { 
     get { return Interlocked.Read(ref m_LayoutSuspended) != 1; } 
    } 

¿Estaba pensando que algo así sería más fácil con un candado? De hecho, será utilizado por varios hilos, por lo que se decidió el uso de bloqueo/enclavamiento.

Respuesta

8

Personalmente me gustaría usar un booleano volátil:

private volatile bool m_LayoutSuspended = false; 
public void SuspendLayout() 
{ 
    m_LayoutSuspended = true; 
} 

public void ResumeLayout() 
{ 
    m_LayoutSuspended = false; 
} 

public bool IsLayoutSuspended 
{ 
    get { return m_LayoutSuspended; } 
} 

Por otra parte, como he reconocido recientemente en otros lugares, volátil, no quiere decir exactamente lo que pensé que lo hizo. Sospecho que esto está bien aunque :)

Incluso si te quedas con Interlocked, lo cambiaría a int ... no hay necesidad de hacer que los sistemas de 32 bits tengan dificultades para hacer un atómico de escritura de 64 bits cuando puedan hacerlo fácilmente con 32 bits ...

+0

@Jon: Tengo curiosidad, ¿pueden dar más detalles sobre "volátil no significa exactamente lo que pensé que era"? – LukeH

+0

@Luke: estoy planeando detallarlo en una publicación de blog en algún momento, pero http://www.bluebytesoftware.com/blog/2008/06/13/VolatileReadsAndWritesAndTimeliness.aspx es la mayor parte. –

+0

Solo para enfatizar, una longitud volátil sería ** no ** segura (en un sistema de 32 bits). –

13

Si lo que está haciendo es seguro desde el punto de vista de alcanzar el campo m_LayoutSuspended carrera, sin embargo, se requiere un bloqueo por la siguiente razón si el código hace lo siguiente:

if (!o.IsLayoutSuspended) // This is not thread Safe ..... 
{ 
    o.SuspendLayout(); // This is not thread Safe, because there's a difference between the checck and the actual write of the variable a race might occur. 
    ... 
    o.ResumeLayout(); 
} 

Una forma más segura, que usa CompareExchange para asegurarse de que no haya carreras las condiciones han ocurrido:

private long m_LayoutSuspended = 0; 
public bool SuspendLayout() 
{ 
    return Interlocked.CompareExchange(ref m_LayoutSuspended, 1) == 0; 
} 

if (o.SuspendLayout()) 
{ 
    .... 
    o.ResumeLayout(); 
} 

O mejor aún, simplemente use un candado.

+0

[Interlocked.CompareExchange no tiene una sobrecarga con dos argumentos ] (https://msdn.microsoft.com/en-us/library/system.threading.interlocked (v = vs.110) .aspx) quizás su línea debería leer 'return Interlocked.CompareExchange (ref m_LayoutSuspended, 1, 0) == 0; ' –

+0

Me ha [también me han señalado] (https://meta.stackoverflow.com/questions/320996/changed-edit-still-doesnt-compile#comment333601_320996) que cambiarlo a' return Interlocked.Exchange (ref m_LayoutSuspended, 1) == 0; 'también hará el truco. –

Cuestiones relacionadas