Interlocked用于增加/模仿布尔值,这样安全吗?

Sar*_*ton 11 c# multithreading interlocked

我只是想知道这个代码是否是一个开发人员(后来已经离开)是好的,我想他想避免锁定.这与仅仅使用直接锁之间有性能差异吗?

    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; }
    }
Run Code Online (Sandbox Code Playgroud)

我认为锁定这样的东西会更容易吗?它确实会被多个线程使用,因此决定使用锁定/互锁的原因.

Pop*_*lin 13

是的,从比赛的角度来看,你所做的是安全的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();
} 
Run Code Online (Sandbox Code Playgroud)

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

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

if (o.SuspendLayout()) 
{
  ....
  o.ResumeLayout();
}
Run Code Online (Sandbox Code Playgroud)

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


Jon*_*eet 10

我个人使用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; }
}
Run Code Online (Sandbox Code Playgroud)

然后,正如我最近在其他地方承认的那样,挥发性并不意味着我的想法.我怀疑这是可以的:)

即使你坚持下去Interlocked,我也会把它改成int......当32位系统可以用32位容易地做到时,没有必要让32位系统有可能难以制造64位写入原子...

  • volatile仅在一组线程专门写入一个字段并且一组线程专门读取一个字段时才有用,除了它没有多大用处. (2认同)