【问题标题】:Interlocked used to increment/mimick a boolean, is this safe?用于增加/模仿布尔值的互锁,这安全吗?
【发布时间】:2009-09-07 13:27:37
【问题描述】:

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

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

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

【问题讨论】:

    标签: c# multithreading interlocked


    【解决方案1】:

    是的,从比赛的角度来看,您正在执行的操作是安全的,到达 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();
    }
    

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

    【讨论】:

    【解决方案2】:

    我个人会使用 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; }
    }
    

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

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

    【讨论】:

    • @Jon:我很好奇,您能否详细说明“易失性并不像我想象的那样”?
    • 只是强调一下,volatile long 将是安全的(在 32 位系统上)。
    • volatile 仅在一组线程专门写入一个字段并且一组线程专门读取一个字段时才有用,除了它没有多大用处。
    • @Pop:你的答案绝对是一个更清晰的答案,但你是否同意 volatile 布尔值与原始代码一样有效?
    • @Jon:是的,volatile bool 应该和原始代码一样安全(但更有效)。但是,比较然后更改的场景并不安全;为此,您需要 Pop 的代码。 (两者都比锁更有效。)
    猜你喜欢
    • 2011-04-18
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多