C# 多线程知识总结
基本概念
什么是线程
- 线程是操作系统中能独立运行的最小单位,也是程序中能够并发执行的一段指令序列。
- 线程是进程的一部分,一个进程可以包含多个线程,这些线程共享进程的资源。
- 进程有入口线程,也可以创建更多的线程。
为什么要多线程
- 批量重复任务希望同时执行(比如对数组中的每个元素进行相同且耗时的操作)。
- 多个不同任务希望同时进行,互不干扰(比如有多个后台线程需要做轮询等操作)。
什么是线程池
- 一组预先创建的线程,可以被重复使用来执行多个任务。
- 避免频繁地创建和销毁线程,从而减少了线程创建和销毁的开销,提高了系统的性能和效率。
- 异步编程默认使用了线程池。
什么是线程安全
线程安全
- 多个线程访问共享资源,对共享资源的访问不会导致数据不一致或不可预期的结果。
同步机制
- 用于协调和控制多个线程之间的执行顺序和互斥访问共享资源。
- 确保线程按照特定的顺序执行,避免竞态条件和数据不一致的问题。
原子操作
- 在执行过程中不会被中断的操作,不可分割,要么完全执行,要么完全不执行,没有中间状态。
- 在多线程环境下,原子操作能够保证数据的一致性和可靠性,避免出现竞态条件和数据竞争的问题。
- 比如Interlocked.Increment(ref count);
常见实现方式
线程
new Thread();
线程池
ThreadPool.QueueUserWorkItem(new WaitCallback((arg) => { }),new object());
异步编程
Task.Run(()=>{});
C#自带方法
- Parallel:提供了For&ForEach(每个元素可同时进行操作)、Invoke(传入多个回调函数,它们可以同时进行)
- PLINQ
- AsParallel:可以将可枚举类型(IEnumable)转为并行执行。+AsOrdered(来保证输出是顺序的)。
- AsSequential:转回为非并行。
实战
线程
线程的创建
- 创建Thread实例,并传入ThreadStart委托,还可以配置线程(如:实际是后台线程)。
- 调用Thread.Start方法,还可以传参。
线程的终止
- 调用Thread.Join方法,等待线程的结束(主线程会被阻塞)。
- 调用Thread.Interrupt方法,中断线程的执行。
- 会在相应线程抛出ThreadInterruptedException异常,需要Catch到这个异常即可。
- 如果线程中包含while(true)循环,那么需要保证包含等待方法,如IO操作或Thread.Sleep(0/1);为了保证该线程能抛出ThreadInterruptedException异常并被捕获。
- 不能用Abort方法:过时了,不安全
- 使用Abort方法来强制终止线程可能导致一些严重的问题,包括资源泄露和不可预测的行为。
- 较新版本的NET版本,调用这个方法,会报PlatformNotSupportedException异常。
- 推荐使用Thread.Interrupt或CannellationToken。
线程的挂起与恢复
- Thread.Suspend以及Thread.Resume
- 较新版本的NET中,这两个方法已经被标记为Obsolete,且调用会报错
- 推荐使用锁、信号量等方式实现这一逻辑。
线程安全与同步机制Thread-Safety
原子操作
- Interlocked
锁与信号量
- lock&Monitor:lock语句,底层是使用Monitor实现的。
- Mutex:互斥锁,进程间共享
- Semaphore:限制同时执行的线程个数。WaitOne等待获取到锁,工作完成后要Release释放锁。Semaphore使用完之后记得Dispose掉。
- WaitHandle
- ManualResetEvent
- AutoResetEvent
- ReaderWriterLock:读写锁,多个线程都可以读,只有一个线程可以写。而且读写是互斥的。
轻量型
- SemaphoreSlim
- ManualResetEventSlim
- AutoResetEventSlim
- ReaderWriterLockSlim
不要自己造轮子!
- 线程安全的单例:Lazy
public class SingletonBase<TSingleton> where TSingleton : class { private static readonly Lazy<TSingleton> _instance = new Lazy<TSingleton>(() => (TSingleton)Activator.CreateInstance(typeof(TSingleton), true)!); /// <summary> /// protected修饰的构造函数不能被创建,可以被继承 /// </summary> protected SingletonBase() { } public static TSingleton Instance => _instance.Value; } - 线程安全的集合类型:ConcurrentBag、ConcurrentStack、ConcurrentQueue、ConcurrentDictonary。
- 阻塞集合:BlockingCollection(阻塞当前线程,不适用异步编程),生产者消费者模型。
- 通道:Channel
- 原子操作:Interlocked
- 周期任务:PerioDicTimer

浙公网安备 33010602011771号