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
posted @ 2025-06-10 15:05  星渐渐被你吸引  阅读(26)  评论(0)    收藏  举报