从C#中的多个线程写入bool变量?

时间:2016-09-30 09:51:55

标签: c# multithreading task-parallel-library

我需要检查Parallel.ForEach的任何迭代是否到达特定点。根据我的理解,如果我的boolvolatile字段,则以下内容是安全的,但它必须是封闭方法中的变量:

bool anySuccess = false;
Parallel.ForEach(things, thing =>
{
    // stuff happens...
    anySuccess = true;
});
if(!anySuccess)
    throw new Exception("No things succeeded :(");

我可以按原样使用此代码,还是应该使用lockInterlocked功能?

2 个答案:

答案 0 :(得分:3)

如果该代码是循环访问该布尔值的 ENTIRETY ,那么对我来说似乎是安全的。

通常基本值类型在某些意义上不是线程安全的,因为对它们执行的许多操作都不是原子的。

但是,如果您正在做的 ONLY 事情是分配给该变量......从不读它,永远不要根据它改变分支,永远不要根据它的当前状态写入它。并且所有写入都是相同的(唯一可能发生的修改是将其设置为true)然后我没有看到任何非原子性导致问题的方法。

<强> == ADDITION ==

以上对当前代码的正确性的评论。作为代码库的一部分,还需要考虑代码在其上下文中的长期安全性。让代码保持原样,正在为未知的开发人员设置一个陷阱,他不了解/了解/识别正在发生的事情,以及为什么它当前是安全的。

如果你这样离开,那么必须对声明和单一用法进行CLEAR评论,说明发生了什么,为什么它是安全的,以及为什么他们不能开始阅读/使用其他变量方式。

替代方案(添加锁定代码)是长期更安全的,但也可能性能稍差。

答案 1 :(得分:-2)

我会锁定布尔。另外,我建议将你的if语句移动到Parallel.Foreach块中。原因是:

这将在并行循环之后进行评估,因此只读取anySuccess的最后一次更新

bool anySuccess = false;
Parallel.ForEach(things, thing =>
{
    // stuff happens...
    anySuccess = true;
});
if(!anySuccess)
    throw new Exception("No things succeeded :(");

这将评估bool的所有更新

Object myLock = new Object();

bool anySuccess = false;
Parallel.ForEach(things, thing =>
{
    // stuff happens...
    lock (myLock) 
    {
        anySuccess = true;
    }
    if(!anySuccess)
        throw new Exception("No things succeeded :(");
});