线程,看到这两个字我不由的想起了Windows操作系统下的“任务管理器”中的进程选项卡,我知道线程和它有关联至于是什么关系是不知道的。不过在学习了Delphi中的多线程后,才对线程有了大概的了解。说是大概实际上是一种无奈的表现,我看的这本书中对于线程只介绍了下概念-------“线程是由一个堆栈、CPU寄存器的状态和系统调试列表中的一个入口组成,每个线程都可以访问进程中的所有资源”,这个抽象的介绍除了能知道进程包含线程外,其它的是越看越糊涂;书中也介绍了在DELPHI中线程类的派生和对线程实例如何操作,对同步、事件、临界也做了介绍,不过和对概念的介绍一样最终的结果是让看书的人不知所云!        还好有网络在,我最终还算是找到了比较满意的答案!经过三天对文章的分析,终于理解了线程、主线程、临界、事件、waitfor这些重要的东西。下面对这几天的学习做个总结:       概念部分:       1、线程        线程本质上是进程中一段并发运行的代码。一个进程至少有一个线程,即所谓的主线程。同时还可以有多个子线程。当一个进程  中用到超过一个线程时,就是所谓的“多线程”       2、同步       说到同步,有一个题外话:加拿大滑铁卢大学的教授李明曾就Synchronize一词在“线程同步”中被译作“同步”提出过异议,个人认为他说的其实很有道理。 中文中“同步”的意思是“同时发生”,而“线程同步”目的就是避免这种“同时发生”的事情。而在英文中,Synchronize的意思有两个:一个是传统意义上的同步(To occur at the same time),另一个是“协调一致”(To operate in unison)。在“线程同步”中的Synchronize一词应该是指后面一种意思,即“保证多个线程在访问同一数据时,保持协调一致,避免出错”。    3、临界区   CriticalSection则是一项共享数据访问保护的技术。它其实也是相当于一个全局的布尔变量。但对它的操作有所不同,它只有两个操作:Enter和Leave,同样可以把它的两个状态当作True和False,分别表示现在是否处于临界区中。这两个操作也是原语,所以它可以用于在多线程应用中保护共享数据,防止访问冲突。
用临界区保护共享数据的方法很简单:在每次要访问共享数据之前调用Enter设置进入临界区标志,然后再操作数据,最后调用Leave离开临界区。它的保护原理是这样的:当一个线程进入临界区后,如果此时另一个线程也要访问这个数据,则它会在调用Enter时,发现已经有线程进入临界区,然后此线程就会被挂起,等待当前在临界区的线程调用Leave离开临界区,当另一个线程完成操作,调用Leave离开后,此线程就会被唤醒,并设置临界区标志,开始操作数据,这样就防止了访问冲突。    4、事件    (Event)与Delphi中的事件有所不同。从本质上说,Event其实相当于一个全局的布尔变量。它有两个赋值操作:Set和Reset,相当于把它设置为True或False。而检查它的值是通过Waitfor 操作进行。对应在Windows平台上,是三个API函数:SetEvent、ResetEvent、WaitForSingleObject(实现WaitFor功能的API还有几个,这是最简单的一个)。    5、waitfor        功能是检查Event的状态是否是Set状态(相当于True),如果是则立即返回,如果不是,则等待它变为Set状态,在等待期间,调用WaitFor的线程处于挂起状态。另外WaitFor有一个参数用于超时设置,如果此参数为0,则不等待,立即返回Event的状态,如果是INFINITE则无限等待,直到Set状态发生,若是一个有限的数值,则等待相应的毫秒数后返回Event的状态。
当Event从Reset状态向Set状态转换时,唤醒其它由于WaitFor这个Event而挂起的线程,这就是它为什么叫Event的原因。所谓“事件”就是指“状态的转换”。通过Event可以在线程间传递这种“状态转换”信息。        到这儿做个小的总结。明眼人都能看出来我在网上找的这篇文章中对线程及其相关概念介绍的很清楚明了,比起书中过于抽象的话语,这些介绍更像是出自真正的程序员。这几个概念中我个人认为waitfor是为事件而生的,通过waitfor可以得知事件的状态。如果事件处于SET,那么waitfor立刻返回告知处于挂起状态的线程重新启动(waitfor的值应该也是个类似于布尔的值)。临界区貌似事件和Waitfor的合成体,在没有其它过程的帮助下临界区可以对处于该区中的数据做到保护。关于临界区的保护方法我自己做了一个图如下假设已经设置好了临界区的数据内容,现在来对流程做一个说明。当有线程0来访问临界区时首先经过第一道关卡:设置临界区状态为ENTER,然后线程0才能访问到处于临界区中保护的数据,最后一道关卡是离开临界区,这是一个完整的流程。现在假设线程0正在访问数据,此时线程1又提出同样的访问要求,此时临界区通过检查临界区标志来决定线程1能否访问,结果发现此时临界标志处于ENTER,那么它就发送一个挂起线程1的指令“现在线程0正在访问数据,它比你先到,所以必须等他访问完成后你才能进去,你现在必须稍等一会”,当线程0访问完成后退出了临界区,此时临界区处于LEAVE状态,这个时候临界区又发送一条指令给线程1“好了不要睡了,线程0已经退出了,你可以进来了”,这样就唤醒了处于“休眠”状态的线程1