12

我只是想知道一个开发人员(后来离开)的代码是否可以,我认为他想避免加锁。这与仅使用直接锁定之间是否存在性能差异?

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

我在想这样的事情用锁会更容易吗?它确实会被多个线程使用,因此决定使用锁定/互锁的原因。

4

2 回答 2

14

是的,从比赛的角度来看,您正在做的事情是安全的m_LayoutSuspended,但是如果代码执行以下操作,则出于以下原因需要锁定:

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

一种更安全的方法,用于CompareExchange确保没有发生竞争条件:

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

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

或者更好的是简单地使用锁。

于 2009-09-07T13:48:22.777 回答
10

我个人会使用一个不稳定的布尔值:

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

再说一次,正如我最近在其他地方所承认的那样,volatile 并不像我想象的那样。我怀疑这没关系:)

即使您坚持使用Interlocked,我也会将其更改为int... 当 32 位系统可以轻松地使用 32 位进行写入时,没有必要让 32 位系统可能难以实现 64 位写入原子...

于 2009-09-07T13:31:41.487 回答