gpt4 book ai didi

c# - Interlocked.Increment() 没有按照我在任务并行库中期望的方式工作

转载 作者:太空狗 更新时间:2023-10-29 20:47:49 25 4
gpt4 key购买 nike

我有一个 Parallel.ForEach() 循环,它获取一个 URL 列表并下载每个 URL 以进行一些额外的处理。在我的循环之外,我已经声明了一个循环计数器变量,并且在循环体内我使用了 Interlocked.Increment() 认为这将是保持“线程安全”的最佳方式,以便在执行每个循环交互时增加计数。

int counter = 0;

Parallel.ForEach(urlList, (url, state) =>
{
// various code statments

Interlocked.Increment( ref counter );

Debug.WriteLine(" ......... counter: " + counter);
});

我原以为我会看到类似的东西:

 ......... 1
......... 2
......... 3
......... 4
......... 5
.........
.........
......... n

但我得到的是 16 "......... 0"(这是因为我有一台双四核计算机,有 8 个 native 内核,但启用了超线程,总共有 16 个内核).然后我会开始看到计数器在大多数情况下正常递增,但有时我会在调试输出中看到重复甚至三次计数器值。

使用 Parallel.ForEach() 计算循环迭代次数的最佳方法是什么?感谢您的任何建议。

最佳答案

Interlocked.Increment 将返回您增加的值。

所以,

int counter = 0;

Parallel.ForEach(urlList, (url, state) =>
{
// various code statments

var counterNow = Interlocked.Increment( ref counter );

Debug.WriteLine(" ......... counter: " + counterNow);
});

应该在递增时返回计数器值。

当您在多处理器/多核机器上运行并拥有多个应用程序线程时,您需要注意,您看到的变量值可能并不反射(reflect)该变量的实际当前状态。这是因为可能有很多单独的缓存,对于每个 CPU 或 die 或 socket,您的线程可以读取缓存的值(节省一次读取主内存的命中)

如果您只想读取一个由多个线程更新的值,您应该使用 Interlocked.Read() 来保证您拥有 counter 的当前值。

关于c# - Interlocked.Increment() 没有按照我在任务并行库中期望的方式工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4772757/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com