C# 多线程总结

1. 多线程基础概念

  • 线程(Thread):操作系统能够调度的最小执行单元

  • 多线程优势:提高CPU利用率、改善响应性、简化异步操作

  • 多线程挑战:线程安全、死锁、竞态条件、资源争用

2. 创建线程的几种方式

(1) Thread类(最基础)

Thread thread = new Thread(() => {
    // 线程执行的代码
});
thread.Start();

(2) ThreadPool(线程池)

ThreadPool.QueueUserWorkItem(state => {
    // 后台线程执行的代码
});

(3) Task(推荐使用)

// 方式1:直接启动
Task.Run(() => {
    // 异步执行的代码
});

// 方式2:使用TaskFactory
Task.Factory.StartNew(() => {
    // 任务代码
});

(4) Parallel类(并行循环)

Parallel.For(0, 10, i => {
    // 并行执行的循环体
});

(5) async/await(异步编程模型)

async Task MyMethodAsync()
{
    await Task.Run(() => {
        // 异步操作
    });
}

3. 关键概念和技术

线程同步机制

  1. lock/Monitor - 最基本的锁机制

  2. private readonly object _lock = new object();
    lock(_lock) { /* 临界区 */ }
  3. Mutex - 跨进程同步

    using var mutex = new Mutex(false, "MyMutex");
  4. Semaphore/SemaphoreSlim - 信号量控制并发数

    using var semaphore = new SemaphoreSlim(3); // 最多3个线程
    await semaphore.WaitAsync();
  5. ManualResetEvent/AutoResetEvent - 事件通知

    var resetEvent = new ManualResetEvent(false);
  6. ReaderWriterLockSlim - 读写分离锁

    var rwLock = new ReaderWriterLockSlim();

线程安全集合

  • ConcurrentDictionary<TKey, TValue>

  • ConcurrentQueue<T>

  • ConcurrentStack<T>

  • ConcurrentBag<T>

  • BlockingCollection<T>

4. 任务并行库(Task Parallel Library, TPL)

Task关键特性

// 任务创建和配置
var task = new Task(() => { }, TaskCreationOptions.LongRunning);

// 任务延续
task.ContinueWith(t => { /* 任务完成后执行 */ });

// 任务取消
var cts = new CancellationTokenSource();
var task = Task.Run(() => { }, cts.Token);
cts.Cancel();

Parallel类

Parallel.Invoke(
    () => DoWork1(),
    () => DoWork2(),
    () => DoWork3()
);

Parallel.ForEach(collection, item => Process(item));

5. 异步编程(async/await)

最佳实践

public async Task<int> GetDataAsync()
{
    // I/O密集型操作使用异步
    var data = await httpClient.GetStringAsync(url);
    return ProcessData(data);
}

// 避免async void,除非是事件处理器
public async Task ProcessAsync()
{
    await Task.Delay(1000);
}

6. 性能注意事项

线程池优化

// 调整线程池
ThreadPool.SetMinThreads(100, 100);
ThreadPool.SetMaxThreads(1000, 1000);

ValueTask优化

public ValueTask<int> GetValueAsync()
{
    // 如果结果可能同步完成,使用ValueTask减少开销
    if (_cache.TryGetValue(key, out var value))
        return new ValueTask<int>(value);
    
    return new ValueTask<int>(FetchAsync());
}

7. 常见问题与解决方案

问题1:死锁

  • 解决方案:避免嵌套锁、统一锁顺序、使用超时机制

问题2:竞态条件

  • 解决方案:使用原子操作、锁机制、不可变对象

问题3:线程过多

  • 解决方案:使用线程池、限制并发数、异步I/O

8. 现代多线程编程建议

  1. 优先使用Task而非Thread

  2. 使用async/await处理I/O密集型操作

  3. 避免线程阻塞,使用异步等待

  4. 使用线程安全集合

  5. 合理使用CancellationToken

  6. 注意内存屏障和可见性问题

  7. 使用并发分析工具调试

总结

C#的多线程编程已经从原始的Thread类发展到以Task和async/await为核心的现代异步编程模型。建议在新项目中优先使用TPL和async/await,它们提供了更好的性能、可维护性和错误处理机制。对于CPU密集型并行计算,Parallel类是一个很好的选择。始终记住线程安全原则,合理使用同步机制,避免常见的并发问题。

C#网络编程总结

TCP/IP与UDP的区别

服务器编码步骤:

客户端编码步骤:

Linq语言集成查询

我们可以为实现`IEnumerable <T>`或` IQueryable <T>`接口的类编写LINQ查询。。

多表联查,关键字:join

自定义聚合,关键字:Aggregate

动态查询

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐