首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >对于每个产生不同结果的Parallel.Foreach :为什么我的代码不安全?

对于每个产生不同结果的Parallel.Foreach :为什么我的代码不安全?
EN

Stack Overflow用户
提问于 2021-09-13 06:31:20
回答 1查看 170关注 0票数 2

我有一个文本文件,我读取到一个字符串content。要识别要进一步处理的文本正文,我将获取字符串中关键字的索引,然后将“启动”索引设置为找到的最小索引。

我和Parallel.ForEach试过这个..。

代码语言:javascript
复制
ConcurrentBag<int> indexes = new();
int index;

switch (Case)
{
    case 1:
        Parallel.ForEach(KeywordTypes.GetImplementedNamedObjects(), inos =>
        {
            index = content.IndexOf($"/begin {inos}");
            index = index == -1 ? content.Length : index;
            indexes.Add(index);
        });
        index = indexes.Min();
        return index;

..。以及使用foreach

代码语言:javascript
复制
foreach (string inos in KeywordTypes.GetImplementedNamedObjects())
{
    index = content.IndexOf($"/begin {inos}");
    index = index == -1 ? content.Length : index;
    indexes.Add(index);
}

index = indexes.Min();
return index;

其中,foreach产生预期的结果,但Parallel.ForEach没有。

为什么我的代码不安全?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-13 06:34:59

这里只有一个index变量,因为它是“捕获”的。这意味着多个线程可以为它争吵,而不是每个线程都有自己的版本。

考虑:

线程A计算index = content.IndexOf($"/begin {inos}");

  • thread B计算index = content.IndexOf($"/begin {inos}"); - oops,线程A的版本刚刚得到了overwritten

  • thread A,使用B只是updated

  • etc

index计算index = index == -1 ? content.Length : index;

重点是:一个值由于线程争用而丢失。

只需移动index的声明就可以修复这个问题:

代码语言:javascript
复制
Parallel.ForEach(KeywordTypes.GetImplementedNamedObjects(), inos =>
{
    var index = content.IndexOf($"/begin {inos}");
    ...

从根本上说,变量的作用域是由其声明的位置定义的。如果一个变量在本地方法/ lambda之外声明,编译器会尊重您所要求的内容,并且该变量在该本地方法/ lambda的所有用途之间共享;如果它在本地方法/lambda中声明,则该生存期是该调用的本地变量,调用方之间不共享任何状态。

如果您想确保您没有意外泄漏状态,那么lambda上的static修饰符就可以实现这一点,尽管它也可以防止访问indexes,所以.可能不是你在这里需要的。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69158225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档