线程同步
更新:2007 年 11 月
编写线程应用程序时,可能需要使各单个线程与程序的其他部分同步。同步可以在多线程编程的非结构化特性与同步处理的结构化顺序之间进行平衡。
同步技术具有以下用途:
如果必须以特定顺序执行任务,使用同步技术可以显式控制代码运行的顺序。
- 或 -
使用同步技术可以避免当两个线程同时共享同一资源时可能会发生的问题。
例如,使用同步技术可以使显示过程等待到在另一个线程上运行的数据检索过程完成后再运行。
同步技术
有两种方法可以实现同步,轮询和使用同步对象。有关同步对象的更多信息,请参见高级同步技术。
轮询
轮询通过循环重复地检查异步调用的状态。轮询是效率最低的线程管理方法,因为它重复地检查各个线程属性的状态,因而浪费了大量资源。
例如,可以使用 IsAlive 属性来轮询检查线程是否已退出。使用该属性时应谨慎,因为处于活动状态的线程并不一定正在运行。
可以使用线程的 ThreadState 属性来获取有关线程状态的详细信息。因为线程可以在任意给定时间具有多种状态,所以存储在 ThreadState 中的值可以是 System.Threading.ThreadState 枚举中值的组合。因此,轮询时应仔细检查所有相关线程状态。例如,如果某个线程的状态指示它不是 Running,该线程可能已完成。但该线程也可能处于挂起或休眠状态。
等待线程完成
Thread.Join 方法对于在启动另一任务之前确定线程是否已完成很有用。Join 方法在线程结束前等待一段指定的时间。如果线程在超时之前结束,则 Join 返回 True;否则返回 False。
您可以想像得到,通过轮询来实现对线程运行顺序的控制将牺牲多线程处理的许多优点。由于轮询的效率非常低,因此通常不建议使用这种方式。更有效的方法是使用 Join 方法控制线程。Join 使调用过程在线程完成或调用超时(如果指定了超时的话)之前处于等待状态。之所以称其为“Join”,是因为创建新线程是执行路径中的一个分支。使用 Join 可以重新将单独的执行路径合并为一个线程。
图 1 线程处理
有一点必须清楚:Join 是一个同步调用或阻止调用。调用 Join 或等待句柄的等待方法后,调用过程即会停止,并等待该线程发出信号指示它已经完成。
Sub JoinThreads()
Dim Thread1 As New System.Threading.Thread(AddressOf SomeTask)
Thread1.Start()
Thread1.Join() ' Wait for the thread to finish.
MsgBox("Thread is done")
End Sub
Sub SomeTask()
' Insert code to perform a task here.
End Sub
这些简单的线程控制方法只适用于管理少量线程的情况,对于大型项目使用起来则非常困难。高级同步技术讨论了可用于同步线程的一些技术。