2009-09-07 16 views
8

Mi chiedo solo se questo codice che un altro sviluppatore (che da allora ha lasciato) sia OK, penso che volesse evitare di mettere un lucchetto. C'è una differenza di prestazioni tra questo e solo usando un blocco diretto?Interlockato usato per incrementare/imitare un booleano, è sicuro?

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; } 
    } 

Stavo pensando che qualcosa del genere sarebbe stato più semplice con un lucchetto? Sarà infatti utilizzato da più thread, quindi perché è stato deciso l'uso di bloccaggio/interblocco.

risposta

8

Personalmente userei un valore booleano volatile:

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; } 
} 

Poi di nuovo, come ho recentemente riconosciuto altrove, volatile non significa proprio quello che ho pensato che ha fatto. Sospetto che tutto sia a posto :)

Anche se si rimane con Interlocked, lo cambierei in un int ... non c'è bisogno di rendere i sistemi a 32 bit potenzialmente difficili da fare un atomico di scrittura a 64 bit quando possono farlo facilmente con 32 bit ...

+0

@Jon: Sono curioso, puoi approfondire "volatile non significa esattamente come pensavo"? – LukeH

+0

@Luke: ho intenzione di approfondire in dettaglio in un post del blog, ma http://www.bluebytesoftware.com/blog/2008/06/13/VolatileReadsAndWritesAndTimeliness.aspx è quasi tutto. –

+0

Giusto per enfatizzare, un tempo volatile ** non ** è sicuro (su un sistema a 32 bit). –

13

Sì quello che stai facendo è al sicuro da un punto di vista gara raggiungere il campo m_LayoutSuspended, tuttavia, un blocco è necessario per il seguente motivo se il codice esegue le seguenti operazioni:

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(); 
} 

Un modo più sicuro, che utilizza CompareExchange per assicurarsi che nessuna gara condizioni si sono verificati:

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

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

O meglio ancora utilizzare semplicemente un lucchetto.

+0

[Interlocked.CompareExchange non ha un sovraccarico con due argomenti ] (https://msdn.microsoft.com/en-us/library/system.threading.interlocked (v = vs.110) .aspx) forse la tua riga dovrebbe leggere 'return Interlocked.CompareExchange (ref m_LayoutSuspended, 1, 0) == 0; ' –

+0

Mi ha anche [indicato]] (https://meta.stackoverflow.com/questions/320996/changed-edit-still-doesnt-compile#comment333601_320996) che lo modifica in' ritorno Interlocked.Exchange (ref m_LayoutSuspended, 1) == 0; 'farà anche il trucco. –

Problemi correlati