我正在开发一个多线程应用程序,使用 Task.WhenAll() 来同时处理多个请求。然而,我遇到了意外的行为,共享数据被损坏,可能是由于竞争条件。
代码如下:
public class DataProcessor
{
private static int _counter = 0;
public async Task ProcessDataAsync()
{
var tasks = new List<Task>();
for (int i = 0; i < 1000; i++)
{
tasks.Add(Task.Run(() => IncrementCounter()));
}
await Task.WhenAll(tasks);
}
private void IncrementCounter()
{
_counter++;
}
}
运行此代码后,_counter 的值通常小于 1000,这表明可能会丢失一些增量。如何解决此问题并确保多线程上下文中的线程安全操作?
我现在不知道了
这里的问题是 _counter++ 不是线程安全的。看似简单的增量操作,但实际上涉及三个步骤:
在多线程环境中,多个线程可以同时读取和递增 _counter,从而导致错过更新和竞争条件。这就是为什么 _counter 的最终值常常小于预期的原因。
使用 Interlocked 进行原子操作:Interlocked 类为跨线程共享的变量提供原子操作。 Interlocked.Increment 确保增量操作是原子的和线程安全的。它避免了竞争条件,无需显式锁定。
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
public class DataProcessor
{
// Shared counter, incremented atomically
private static int _counter = 0;
public async Task ProcessDataAsync()
{
const int taskCount = 1000;
var tasks = new List<Task>(taskCount);
// Add tasks to increment the counter
for (int i = 0; i < taskCount; i++)
{
tasks.Add(Task.Run(IncrementCounter));
}
// Wait for all tasks to complete
await Task.WhenAll(tasks);
Console.WriteLine($"Final Counter Value: {_counter}");
}
private void IncrementCounter()
{
Interlocked.Increment(ref _counter); // Atomic increment
}
// Entry point to test the code
public static async Task Main(string[] args)
{
var processor = new DataProcessor();
await processor.ProcessDataAsync();
}
}