[多线程]托管线程处理的最佳做法
多线程处理需在编程时倍加注意。 对于多数任务,通过将执行请求以线程池线程的方式排队,可以降低复杂性。
死锁和争用条件
多线程处理解决了吞吐量和响应性问题,但引入此功能会带来新的问题:死锁和争用条件。
死锁
两个线程中的每一个线程都尝试锁定另外一个线程已锁定的资源时,就会发生死锁。 两个线程都不能继续执行。
托管线程处理类的许多方法都提供了超时设定,有助于检测死锁。例如Monitor.TryEnter。
争用条件
争用条件是程序的结果取决于两个或更多个线程中的哪一个先到达某一特定代码块时出现的一种 bug。 多次运行程序会产生不同的结果,并且无法预测任何给定运行的结果。
争用条件的一个简单例子是递增一个字段。 通过使用 Interlocked 类的方法(如 Interlocked.Increment),可以轻松避免这种争用条件。
一般性建议
使用多线程时需考虑以下准则:
- 请勿使用 Thread.Abort 终止其他线程。
- 请勿使用 Thread.Suspend 和 Thread.Resume 同步多个线程的活动。
- 不要从主程序中控制工作线程的执行(如使用事件)。
- 不要将类型用作锁定对象。
- 锁定实例时要谨慎。
- 请务必针对需要不同资源的任务使用多线程,避免向单个资源指定多个线程。
- 对于简单的状态更改,请考虑使用 Interlocked 类的方法,而不是
lock
语句(Visual Basic 中的SyncLock
)。