2017-03-07 33 views
2

我试图追查一个我认为可能与应用程序多线程相关的错误。我简化了下面的代码:从外部函数锁定和ref值

class Outer { 
    private static int count; 

    //this function is called from multiple threads in quick succession 
    public void DoFoo() { 
    Inner.Increment(ref count); 
    } 
} 

class Inner { 
    private readonly static object mLock = new object(); 
    public static string Increment(ref count) { 
    lock (mLock) (
     if (count > 1000) 
     count = 0; 
     count++; 
    } 
    return count.ToString(); 
    } 
} 

锁定可以保证以这种方式传递的变量的安全吗?有没有任何复制计数正在进行,似乎并不明显,可能会破坏记忆安全?我在想它可能会返回一个新的int值,并在方法末尾执行赋值操作。除此之外,我的理解是锁定部分可以处理任何缓存问题。

将问题买给我们注意的错误看起来是一个陈旧的count版本的线程之一。

回答

2

这里的问题是,写在你的代码中的一些其他线程可以直接读取Outer.count当它是== 0,因为你可以访问Outer.count,而没有首先获得一个锁(通常,count只能前首先为0来电Inner.Increment,从此只能有1和1001)之间的值

无锁可以用这种方式来完成:

class Inner 
{ 
    public static string Increment(ref int count) 
    { 
     while (true) 
     { 
      int original = count; 
      int next = original; 

      if (next > 1000) 
      { 
       next = 0; 
      } 

      next++; 

      if (Interlocked.CompareExchange(ref count, next, original) == original) 
      { 
       return next.ToString(); 
      } 
     } 
    } 
} 

我计算next值,并使用它(通过Interlocked.CompareExchange ) 只有我在此期间,f count没有变化。

+0

这就是我当时的想法,但是当锁定语句被输入(因为它是一个引用)或者它会坚持陈旧值时它会得到最新值吗? – flukus

+0

@flukus看看我修改后的代码。 – xanatos

+0

这样可以解决陈旧价值从外部传入的问题吗? – flukus

相关问题