【问题标题】:resolving threading conflicts in C#解决 C# 中的线程冲突
【发布时间】:2013-05-21 18:22:09
【问题描述】:

假设有一个静态变量被 2 个线程访问。

public static int val = 1;

现在假设线程 1 执行这样的语句

if(val==1)
{
  val +=1
}

然而,在上述语句中的检查之后和添加之前,线程 2 将 val 的值更改为其他值。

现在这会导致一些令人讨厌的错误。这发生在我的代码中。

有什么方法可以让线程 1 注意到 val 的值已更改,而不是添加,而是返回并再次执行检查。

【问题讨论】:

  • 根据您的问题,我建议Interlocked.CompareExchange,如下面的答案中所建议的那样。如果您认为这不合适,您应该更改您的问题,向我们展示您正在尝试解决的真实问题。

标签: c# .net multithreading thread-safety


【解决方案1】:

对于您的示例,您可以:

var originalValue = Interlocked.CompareExchange(ref val, 
                                    2,       //update val to this value
                                    1);      //if val matches this value
if(originalValue == 1)
{
    //the update occurred
}

【讨论】:

  • 好吧,我的示例只是我在代码中面临的问题的简化版本。我认为上述方法在我的真实代码中不会很容易使用。
  • @WinCoder : 看看 Interlocked 提供什么,因为它可能仍然有满足您需求的工具。
【解决方案2】:

你可以使用锁:

var lockObj = new object();

if(val == 1) // is the value what we want
{
    lock(lockObj) // let's lock it
    {
        if(val == 1) // now that it's lock, check again just to be sure
        {
            val += 1;
        }
    }
}

如果走这条路,您必须确保任何修改 val 的代码也使用具有相同锁对象的锁。

lock(lockObj)
{
    // code that changes `val`
}

【讨论】:

  • 在锁外检查 val 的值然后在锁内再次检查似乎不是一个好主意。如果你把对 val 的每一次访问都放在一个锁中,无论是读还是写,你都不用担心在你触摸它之前有人会弄乱它。因此,您获得了锁,然后检查了 val,您可以确定在您这样做之前没有其他人接触过 val。
  • @MichaelMankus - 在您的情况下,无论您是否需要,您最终都会锁定。检查一个值通常很便宜,而获取锁更昂贵,并且可以阻止其他代码等待锁。在en.wikipedia.org/wiki/Double-checked_locking查看推理
  • 好点。我从来没有仔细检查过我的锁。看来我要开始做这件事了。
  • 我无法想象你为什么在这里使用锁而不是Interlocked.CompareExchange
  • @JimMischel - 我使用锁只是因为我认为这是一个简化的示例。如果 OP 真的只是增加值,那么肯定会使用 Iterlocked.CompareExchange 或 Interlocked.Increment 方法。
【解决方案3】:

您可以在访问 val 或更新 val 时使用锁。见http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

【讨论】:

    【解决方案4】:

    如果您希望以线程安全的方式递增整数值,可以使用静态 Interlocked.Increment 方法:Interlocked.Increment Method (Int32)

    【讨论】:

      猜你喜欢
      • 2013-06-13
      • 1970-01-01
      • 1970-01-01
      • 2012-11-25
      • 1970-01-01
      • 2016-04-14
      • 2014-02-26
      • 2012-10-24
      • 1970-01-01
      相关资源
      最近更新 更多