ToB企服应用市场:ToB评测及商务社交产业平台

标题: C# 多线程 [打印本页]

作者: 数据人与超自然意识    时间: 2024-7-19 20:04
标题: C# 多线程
C# 多线程编程基本概念

1. 线程(Thread)


2. 进程(Process)


3. 并发与并行


4. 线程同步与互斥


5. Task 与 Task Parallel Library (TPL)


6. Async/Await


7. 线程池(Thread Pool)


8. 上下文切换


9. 死锁与活锁


10. 线程安全



线程同步

1. lock 关键字

lock 关键字用于确保一次只有一个线程可以执行某个代码块。它通常用于保护共享资源或代码段。
  1. private readonly object lockObject = new object();
  2. public void Method()
  3. {
  4.     lock (lockObject)
  5.     {
  6.         // 访问或修改共享资源
  7.         Console.WriteLine("线程 " + Thread.CurrentThread.ManagedThreadId + " 进入锁");
  8.         // 模拟长时间操作
  9.         Thread.Sleep(1000);
  10.         Console.WriteLine("线程 " + Thread.CurrentThread.ManagedThreadId + " 离开锁");
  11.     }
  12. }
复制代码
2. Monitor 类

Monitor 类提供了与 lock 关键字类似的功能,但提供了更多的灵活性,如尝试获取锁、释放锁等。
  1. private readonly object lockObject = new object();
  2. public void Method()
  3. {
  4.     bool lockTaken = false;
  5.     try
  6.     {
  7.         Monitor.TryEnter(lockObject, 1000, ref lockTaken);
  8.         if (lockTaken)
  9.         {
  10.             // 访问或修改共享资源
  11.             Console.WriteLine("线程 " + Thread.CurrentThread.ManagedThreadId + " 获取锁");
  12.             Thread.Sleep(1000);
  13.         }
  14.         else
  15.         {
  16.             Console.WriteLine("线程 " + Thread.CurrentThread.ManagedThreadId + " 未能获取锁");
  17.         }
  18.     }
  19.     finally
  20.     {
  21.         if (lockTaken)
  22.         {
  23.             Monitor.Exit(lockObject);
  24.         }
  25.     }
  26. }
复制代码
3. Mutex 类

Mutex 是一种跨进程的同步基元,但也可以用于同一进程内的线程同步。
  1. private static Mutex mutex = new Mutex();
  2. public static void Method()
  3. {
  4.     mutex.WaitOne();
  5.     try
  6.     {
  7.         // 访问或修改共享资源
  8.         Console.WriteLine("线程 " + Thread.CurrentThread.ManagedThreadId + " 进入 Mutex");
  9.         Thread.Sleep(1000);
  10.     }
  11.     finally
  12.     {
  13.         mutex.ReleaseMutex();
  14.     }
  15. }
复制代码
4. Semaphore 类

Semaphore 用于控制对共享资源的并发访问数目。
  1. private static Semaphore semaphore = new Semaphore(1, 1); // 允许一个线程访问
  2. public void Method()
  3. {
  4.     semaphore.WaitOne();
  5.     try
  6.     {
  7.         // 访问或修改共享资源
  8.         Console.WriteLine("线程 " + Thread.CurrentThread.ManagedThreadId + " 进入 Semaphore");
  9.         Thread.Sleep(1000);
  10.     }
  11.     finally
  12.     {
  13.         semaphore.Release();
  14.     }
  15. }
复制代码
5. Interlocked 类

Interlocked 类提供了一组静态方法,用于对变量执行简单的原子操作,如递增、递减、比较并交换等。
  1. private int counter = 0;
  2. public void Increment()
  3. {
  4.     Interlocked.Increment(ref counter);
  5. }
  6. public void PrintCounter()
  7. {
  8.     Console.WriteLine("Counter: " + Interlocked.Read(ref counter));
  9. }
复制代码
6. ReaderWriterLockSlim 类

ReaderWriterLockSlim 允很多个线程同时读取共享资源,但写入操作是独占的。
  1. private ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
  2. public void Read()
  3. {
  4.     rwLock.EnterReadLock();
  5.     try
  6.     {
  7.         // 读取共享资源
  8.         Console.WriteLine("线程 " + Thread.CurrentThread.ManagedThreadId + " 正在读取");
  9.         Thread.Sleep(1000);
  10.     }
  11.     finally
  12.     {
  13.         rwLock.ExitReadLock();
  14.     }
  15. }
  16. public void Write()
  17. {
  18.     rwLock.EnterWriteLock();
  19.     try
  20.     {
  21.         // 修改共享资源
  22.         Console.WriteLine("线程 " + Thread.CurrentThread.ManagedThreadId + " 正在写入");
  23.         Thread.Sleep(1000);
  24.     }
  25.     finally
  26.     {
  27.         rwLock.ExitWriteLock();
  28.     }
  29. }
复制代码
7. SpinLock 类

SpinLock 是一种低延迟的锁,适用于预计锁持偶然间非常短的场景。它会让等待锁的线程举行“自旋”,即在一个循环中重复检查锁是否可用,而不是将线程挂起。这减少了线程上下文切换的开销,但也大概增长CPU的利用率。
  1. private SpinLock spinLock = new SpinLock();
  2. public void Method()
  3. {
  4.     bool lockTaken = false;
  5.     try
  6.     {
  7.         spinLock.Enter(ref lockTaken);
  8.         if (lockTaken)
  9.         {
  10.             // 访问或修改共享资源
  11.             Console.WriteLine("线程 " + Thread.CurrentThread.ManagedThreadId + " 进入 SpinLock");
  12.             Thread.Sleep(100); // 假设这是一个非常快的操作
  13.         }
  14.     }
  15.     finally
  16.     {
  17.         if (lockTaken)
  18.         {
  19.             spinLock.Exit();
  20.         }
  21.     }
  22. }
复制代码
8. SemaphoreSlim 类

SemaphoreSlim 是 Semaphore 的一个轻量级版本,专为等待时间较短的场景筹划。它提供了异步等待的能力,非常适合在基于使命的异步编程模式(TAP)中利用。
  1. private SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); // 允许一个线程同时访问
  2. public async Task MethodAsync()
  3. {
  4.     await semaphoreSlim.WaitAsync();
  5.     try
  6.     {
  7.         // 访问或修改共享资源
  8.         Console.WriteLine("线程 " + Thread.CurrentThread.ManagedThreadId + " 进入 SemaphoreSlim");
  9.         await Task.Delay(1000); // 模拟异步操作
  10.     }
  11.     finally
  12.     {
  13.         semaphoreSlim.Release();
  14.     }
  15. }
复制代码
9. Barrier 类

Barrier 用于在并行算法中同步线程,确保全部线程都到达某个公共屏蔽点之后才能继续执行。这对于需要将使命分解为多个阶段,而且每个阶段都需要全部线程完成后才能继续的场景很有用。
  1. private Barrier barrier = new Barrier(3); // 假设有三个线程
  2. public void ThreadMethod(int threadId)
  3. {
  4.     Console.WriteLine($"线程 {threadId} 到达屏障 1");
  5.     barrier.SignalAndWait(); // 所有线程都必须调用这个方法来等待其他线程
  6.     // 执行一些工作
  7.     Console.WriteLine($"线程 {threadId} 完成工作");
  8.     // 可以在屏障上设置回调,当所有线程都到达时执行
  9.     barrier.PostPhaseAction += (b) =>
  10.     {
  11.         Console.WriteLine("所有线程都到达屏障 1,继续执行...");
  12.     };
  13.     // 假设还有一个屏障点
  14.     Console.WriteLine($"线程 {threadId} 到达屏障 2");
  15.     barrier.SignalAndWait();
  16. }
复制代码
留意:上面的 Barrier 示例中,由于 Barrier 的构造函数只定义了参与者的数目,并没有现实的“屏蔽点”概念(除了初始化时的那一次)。在现实应用中,你大概需要多次调用 SignalAndWait 来表现不同的同步点。此外,PostPhaseAction 回调是在每个阶段的全部线程都调用 SignalAndWait 后执行的。
10. CountdownEvent 类

CountdownEvent 允许一个或多个线程等待直到一组操作中的指定数目完成。它对于等待多个并行使命完成并继续执行下一个使命的场景非常有用。
  1. private CountdownEvent countdownEvent = new CountdownEvent(3); // 初始化为3,表示有3个任务需要完成
  2. public void TaskMethod(int taskId)
  3. {
  4.     // 执行一些工作
  5.     Console.WriteLine($"任务 {taskId} 开始执行");
  6.     Thread.Sleep(1000); // 模拟耗时操作
  7.     // 任务完成,信号量减一
  8.     countdownEvent.Signal();
  9.     Console.WriteLine($"任务 {taskId} 完成");
  10. }
  11. public void StartTasks()
  12. {
  13.     for (int i = 1; i <= 3; i++)
  14.     {
  15.         Task.Run(() => TaskMethod(i));
  16.     }
  17.     // 等待所有任务完成
  18.     countdownEvent.Wait();
  19.     Console.WriteLine("所有任务完成");
  20. }
复制代码

并发编程最佳实践与优化

在并发编程中,有用地管理线程和同步机制是确保步伐性能、稳定性和可扩展性的关键。以下是并发编程中的一些最佳实践、优化策略以及重要考量因素,旨在资助您构建高效且可靠的并发系统。
1. 并发聚集的利用


2. 优化锁的利用


3. 制止死锁


4. 异步编程(async 和 await)


5. 性能考量


6. 非常处理


7. 调试与监控


8. 最佳实践


9. 谨慎利用线程池



异步编程模式

极大地简化了异步代码的编写和理解,使得开发者能够以类似于同步代码的方式来编写异步逻辑,而无需深入底层的线程管理或回调机制。async 和 await 关键字是 C# 5.0 引入的两个非常重要的关键字,它们一起工作,使得异步编程变得简单和直观。
async 关键字


await 关键字


示例

下面是一个简单的异步方法示例,该方法利用 HttpClient 异步获取网页的内容:
  1. using System;
  2. using System.Net.Http;
  3. using System.Threading.Tasks;
  4. class Program
  5. {
  6.     static async Task Main(string[] args)
  7.     {
  8.         string content = await GetWebPageAsync("https://www.example.com");
  9.         Console.WriteLine(content);
  10.     }
  11.     static async Task<string> GetWebPageAsync(string url)
  12.     {
  13.         using (HttpClient client = new HttpClient())
  14.         {
  15.             HttpResponseMessage response = await client.GetAsync(url);
  16.             if (response.IsSuccessStatusCode)
  17.             {
  18.                 return await response.Content.ReadAsStringAsync();
  19.             }
  20.             else
  21.             {
  22.                 throw new HttpRequestException($"Status code does not indicate success: {response.StatusCode}");
  23.             }
  24.         }
  25.     }
  26. }
复制代码
在这个示例中,Main 方法被标记为 async,这允许它内部利用 await。GetWebPageAsync 方法是另一个异步方法,它利用 HttpClient 的 GetAsync 方法来异步获取网页,并利用 await 等待操作完成。然后,它读取响应内容并返回。留意,非常处理也是异步编程中的一个重要方面,上述示例展示了如何在异步方法中抛出和捕获非常。

高效异步

在.NET Core(或现在更常见的.NET 5/6/7等)中实现高效的异步操作主要依赖于理解异步编程模式,特别是如何准确利用async和await关键字,以及理解异步操作背后的线程和使命的管理。以下是一些实现高效异步操作的关键点:
1. 理解async和await


2. 制止阻塞调用


3. 并行与并发


4. 异步资源管理


5. 制止不须要的异步


6. 性能测试与调优


7. 利用符合的异步API


8. 监控和日记记录


总之,实现高效的异步操作需要综合思量多个方面,包罗准确利用异步编程模式、制止阻塞调用、优化并行与并发、管理资源、制止不须要的异步以及举行性能测试和调优。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4