c# - 线程表现异常
问题描述
以下在 Windows 10 上运行的 .Net 5 多线程代码应该计算出_sum
非确定性的值,例如 2,4 和 8。但是,_sum
始终为 10,即正确答案。似乎已经应用了锁_sum
。
任何人都可以阐明这个问题吗?
using System;
using System.Threading;
namespace MtAdd
{
class Program
{
private static int _sum = 0; //shared resource
static void Main(string[] args)
{
var threads = new Thread[10];
//Add 1 to _sum for ten times.
for (var i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(AddOne);
threads[i].Start();
}
foreach (var t in threads)
{
t.Join();
}
Console.WriteLine("[{0}] sum = {1}",
Thread.CurrentThread.ManagedThreadId,
_sum);
}
private static void AddOne()
{
Console.WriteLine("[{0}] AddOne called", Thread.CurrentThread.ManagedThreadId);
_sum++; //critical section
}
}
}
[4] AddOne called
[5] AddOne called
[7] AddOne called
[6] AddOne called
[8] AddOne called
[9] AddOne called
[10] AddOne called
[11] AddOne called
[12] AddOne called
[13] AddOne called
[1] sum = 10
解决方案
Three things to increase the probability get a "wrong" answer:
get rid of
Console.WriteLine
: see @Hans explanation in commentsincrease the concurrency: ie if 10 is not enough, try 1_000_000 threads
use
Task.Run(AddOne)
: it will runAddOne
in the thread pool. It costs very little runtime to start a thread from here because the CLR keeps a pool of already-started threads. Whereasnew Thread(action).Start
can take around 100ms to actually create a new thread.
The code below prints 982266 rather than 1000000 on my computer. Try on yours and let us know:
var tasks = new Task[1_000_000];
for (var i = 0; i < tasks.Length; i++)
tasks[i] = Task.Run(AddOne);
Task.WaitAll(tasks);
Console.WriteLine(_sum);
推荐阅读
- python-3.x - 如何修改python中的文本?
- python - 更快的实现 python3 -leetcode 问题集-
- reactjs - index.html 中的脚本文件在主页上工作,但在其他子屏幕上不工作
- javascript - 如何将 webpack 样式加载器随机数属性添加到 craco 配置
- python - 将文件分配给列表
- python - 如何将此 URL 参数字典编码为有效字符串?
- javascript - 比较JavaScript中的两个字符串而不考虑顺序?
- .net - .NET 5 (NET Core 5) 使用针对 .NET Framework 4 构建的库 - 兼容性垫片?
- java - 如何验证 selenium + java 中的排序?
- python - 如何按流派或标题按字母顺序对文本文件中的列表进行排序?