【问题标题】:Thread-safe realization of one-time method一次性方法的线程安全实现
【发布时间】:2012-01-30 11:16:59
【问题描述】:

我有一个方法,它只能被调用一次,例如Dispose。现在,我意识到它是下一个:

private bool _isAlive = true;

public void Dispose()
{
    if (this._isAlive)
    {
        this._isAlive = false;
        //Do Something
    }
}

但它不是线程安全的,因为在比较和将标志 _isAlive 设置为 false 之间存在差距。因此,有可能不止一个线程执行//Do Something 代码。

它有线程安全的变体吗?

【问题讨论】:

  • Thread-safe replace for code? 的可能重复项...特别是考虑到您在这两个问题上得到的答案基本相同。
  • @AndrewBarber 不完全...您链接到的问题类似,但仅涉及防止重入(即并行执行多次)...这个问题是关于一次性执行对象的整个生命周期。
  • 顺便说一句,您完全错误地描述了您的要求。并不是说Dispose() 必须被调用一次以上,它几乎完全相反:Dispose() 必须能够安全地处理被多次调用。
  • 我也是这么想的,但是那里的方法执行了很多次。这里只能执行一次
  • @Yahia 考虑到一个跟随另一个的速度,以及用户提出问题的整体模式,这似乎应该是该问题的一部分。

标签: c# .net multithreading thread-safety


【解决方案1】:

使用(根据cmets更新):

private long _isSomeMethodExecuted = 0;

public void Dispose()
{
 if ( Interlocked.Read ( ref this._isSomeMethodExecuted ) != 0 )
      return;

 if (Interlocked.Increment (ref this._isSomeMethodExecuted) == 1) //check if method is already executed
 {
        //Main code of method

 }
// leave the decrement out - this leads to 
// this method being callable exactly once as in the lifetime of the object
// Interlocked.Decrement (ref this._isSomeMethodExecuted);
}

参考见http://msdn.microsoft.com/en-us/library/zs86dyzy.aspx

更新(根据@LukeH 的评论):

单个CompareExchange 调用更简单/更好:

public void Dispose() 
{ 
if (Interlocked.CompareExchange(ref _isSomeMethodExecuted, 1, 0) == 0) 
{ /* main code of method */ } 
}

【讨论】:

  • 如果方法会被多次调用——“做某事”可以多次执行
  • @Praetor12 no...您可以多次调用该方法,但只有第一次实际执行Main code of method 中的代码,任何后续调用都不会执行任何操作...
  • @Yahia:它会在第一次之后每(2**64)次调用!
  • @LukeH 虽然我怀疑这对运行时有真正的影响,但你绝对是对的......我的错误......
  • @LukeH 更新了代码,所以现在你所描述的不会再发生了。
【解决方案2】:

恕我直言,使用MethodImpAttribute 是最简单的方法。

  public void Dispose()
  {
      if (isAlive && ShouldDispose())
      {
          //Your code here
      }
  }

  [MethodImplAttribute(MethodImplOptions.Synchronized)]
  private bool ShouldDispose()
  {
       if (isAlive)
       {
            isAlive = false;
            return true;
       }
       return false;
  }

【讨论】:

    猜你喜欢
    • 2010-10-17
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 2012-03-20
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    相关资源
    最近更新 更多