王朝网络
分享
 
 
 

进程与线程杂谈(二)

王朝软件设计·作者佚名  2004-11-11
宽屏版  字体: |||超大  

上次说了线程的作用,显然,要使得线程之间能够通讯才能利用好线程,否则,每个线程都各干个的,向一盘散沙,程序就什么也做不了儿了。现在,我们来看看线程间如何通讯。

线程间通讯的方法有很多,常用的有:变量、临界段、Windows消息、事件。

首先来讨论变量。既然线程都处于同一个进程内,它们的地址空间就是相同的,对于完全依赖地址空间的变量来说,当然可以被同在一个进程中的任意一个线程访问,因而就可以用来通讯。

比如,有一个全局变量,两个线程;我们希望第一个线程在工作,而第二个线程等待,当第一个线程检测的某件事发生时,通知第二个线程,使第二个线程开始运行。可以将全局变量置为0,然后让第二个线程进入一个“死循环”,等待全局变量变为1。而第一个线程执行他的任务,当事件发生时,第一个线程将全局变量赋值为1,于是第二个线程便奇妙的结束了他的死循环,开始执行预定的工作。

由此可见,变量确实可以进行线程间的通讯;但不是使用上面的方法(该方法被称为“循环锁”),因为它太拙劣了,第二个线程在等待中要消耗大量的CPU时间,却不作任何事。而且,它不能处理复杂的情况,例如:

还是上两个线程,第一个线程分发任务,第二个线程执行任务;第一个线程每次给全局变量加上一个需执行的任务的数目,第二个线程每次从全局变量中减掉它完成的任务的数目。两个运算都是“全局变量 op 任务数目 → 全局变量”,假设线程一先读取全局变量,是n,然后加上新任务数目,结果是n+p;而就在同时,线程二也读取了全局变量,由于线程一还没来得及将结果写回,线程二读到的也是n,减去完成的任务数,结果是n-q;现在,两个线程都要将结果写回到全局变量,显然这里有问题,最终结果要么是n+p、要么是n-q,总之不是正确的n+p-q。

问题就出在那个“同时”上,如果让线程二等线程一把结果写回全局变量再读取、减去、写回,错误就不会发生。

Windows提供了一个专门针对变量通讯的同步方法——互锁函数。这是一组形如Interlocked???()的函数。每个函数都可以对一个变量进行一种特定的操作,在操作进行中,能够自动保持与其它线程同步——每个函数都执行一种“原子操作”——该操作不能与共用同一资源的其它操作同时进行。

例如,上面的例子,通过使用InterlockedExchangeAdd()来执行加减操作,便可以保证对全局变量的操作不会同时发生。

有时,线程间的通讯过程不像上述的那样简单、仅仅是做一次加减法,而是由许多步组成的。比如,线程一除了加上任务数外,还要填写每个任务的具体参数,线程一进而希望在自己填写完全部所需数据后,线程二再对它们修改,原因类似。这是可以使用临界段。

CRITICAL_SECTION类型声明一个临界段结构变量,然后用InitializeCriticalSection()初始化它。EnterCriticalSection()和LeaveCriticalSection()两个API分别指示进入或退出临界段,参数是一个已经定义的临界段。在临界段内的一组操作都是原子的,它们不能与共用同一临界段的另外一组操作同时进行。

与互锁函数的不同是,互锁函数仅涉及一个共享资源,执行一个操作,因而没有该保护哪些资源、保护多长时间的问题;临界段涉及多个资源,执行多个操作,因而需要一个变量来代表对一类资源和操作的保护。

Windows的消息机制就是用来通讯的,它本身就支持线程间通讯。消息一般是基于窗口的,而窗口是属于创建它的线程的。两个属于不同线程的窗口可以通过Windows消息来通讯。例如上面线程二等待的情况就可以让线程二调用GetMessage()等待消息,当线程一使用PostMessage()将消息发送给线程二时,GetMessage()将返回,线程二可以执行相应的任务。消息的两个参数可以用来携带对任务的描述。即便一个线程没有窗口,其它线程也可以使用PostThreadMessage()将消息直接发给该线程。使用Windows消息来通讯,是一对一的进行的,在某些场合,可能需要一对多、多对一或多对多的通讯,这时,可以借助事件(Event)来完成。CreateEvent()创建一个事件,事件有两种状态——已触发和未触发。SetEvent()用来触发一个事件,ResetEvent()用来恢复事件到未触发状态。一组“等待函数”用来检测事件的状态,例如WaitForSingleObject()等待一个事件,直到事件的状态为已触发时才返回。与上面Windows消息的例子类似,它也可以用于让线程二等待,更方便的是,如果有另外的线程三做与线程二类似的工作,它可以等待同一个事件,线程一的一次SetEvent()将同时通知两个线程执行任务;如果有线程零做与线程一类似的工作,它也可以触发同一个事件,线程零或线程一任意一方触发事件都将使两个线程执行任务。

除了上述的几种方法以外,旗语等方法也是用来进行线程间通讯的,这里先不作介绍。

当设计线程间的通讯时,一定要时刻记得各个线程之间是异步运行的,必须要使用某种机制才能进行通讯,在实际中,情况可能会非常复杂,如果考虑不全面,结果将是难以预料的。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有