分享
 
 
 

WINDOWS下线程同步探讨

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

本文主要讨论WINDOWS应用层编程的线程同步问题。在实际编程过程中,我们经常会遇到线程同步的问题,例如在编写多线程共同访问一个共享资源的程序时,如果多个线程只是读取资源那么就不会涉及到下面我们要讨论的问题;如果当有的线程读取资源,有的线程改变资源时,就会产生资源在访问时的同步问题。即当一个线程改变资源,同时其他线程也在读写该资源,这样会导致资源内容的不可确定性。为避免这种情况的发生,保证资源的完整性,我们通常会采用线程同步的方法。WINDOWS操作系统为我们提供了事件(EVENT)、信号量(SEMAPHORE)、互斥(MUTEX)等内核对象来同步线程,同时也提供了关键代码段(CRITICAL_SECTION)这样的用户方式来进行同步。下面我就对这两种情况分别来讨论。

内核对象方式:WINDOWS内核提供的可以用来进行线程同步的内核对象,都是可以发信号(Signaled)的对象,在WINDOWS中它们被称为“调度程序对象”(dispatcher object)。它们包括进程(PROCESS)、线程(THREAD)、事件(EVENT)、信号量(SEMAPHORE)、互斥(MUTEX)、时钟(TIMER)等。对这一类的对象,线程都可以通过用WaitForSingleObject()或WaitForMultpleObjects()等API来获得对象的使用权。当对象处于信号态时,线程立即返回,获得对象的使用权。当对象未处于信号态时,即对象正被其他线程占用时,线程就会被排在该内核对象的等待队列当中,当对象变为信号态时,队列中排队的第一个线程便得到该对象,被内核放入线程就绪队列,已重新获得CPU时间。在线程使用完对象后,需要释放该对象的使用权,以便其它等待该对象的线程获得执行。相关对象操作的API在MSDN中有详细的描述,这里就不再复述。下面简单讨论一下,WINDOWS的内核实现:

相关结构

typedef struct _DISPATCHER_HEADER {

UCHAR Type;

UCHAR Absolute;

UCHAR Size;

UCHAR Inserted;

LONG SignalState;

LIST_ENTRY WaitListHead;

} DISPATCHER_HEADER;

typedef struct _KWAIT_BLOCK {

LIST_ENTRY WaitListEntry;

struct _KTHREAD *RESTRICTED_POINTER Thread;

PVOID Object;

struct _KWAIT_BLOCK *RESTRICTED_POINTER NextWaitBlock;

USHORT WaitKey;

USHORT WaitType;

} KWAIT_BLOCK, *PKWAIT_BLOCK, *RESTRICTED_POINTER PRKWAIT_BLOCK;

(注:这两个结构包含NTDDK.H中,是公开的)

在下面的图(1)中我们看到,线程1在等待对象B,线程2在等待对象A,B。如果对象A变为信号状态,内核将会检测到线程2在等待该对象,但由于线程2还在等待对象B,那么线程2还不能被放入线程就绪队列,以重新获得CPU。如果对象B变为信号

图(1)

状态,那么线程1由于没有等待其它对象,而被内核放入就绪队列并执行。而线程2则需等待线程1释放对象B后才可被安排获得执行。对于不同的内核对象,内核在处理等待它们的线程时也不尽相同,对于进程,线程等内核对象,当对象变为信号状态时,内核将一次使所有等待线程都获得使用权。要对此详细了解的朋友可以看《Inside Windows 2000》。

用户方式:在WINDOWS下,WINDOWS还给用户提供了关键代码段(CRITICAL_SECTION),这种用户方式的线程同步解决方法。这种方式,比内核对象方式执行快。因为每次检测内核对象是否被占用时,系统都要由用户模式换为核心模式,这样就要消耗不少的切换时间。而关键代码段只是在用户模式下被简单检测是否已被其它线程占用,这样就比内核对象少了模式间切换所用的时间。在需要同步保护的代码量不是很大的情况下,使用关键代码段不失为一个好的解决方法,它可以提高代码的执行效率,减少线程间的冲突。当关键代码段发生冲突时,即一个线程检测到关键代码段已被其他线程占用时,该线程就进入等待状态。关键代码段有一个等待超时,如果超时发生时,线程仍未获得关键代码段,就会产生一个异常。所以,在编写关键代码段程序时应当注意用完后释放。关键代码段的超时值被记录在注册表的HKEY_LOCAL_MACHINE\System\CurrentControSet\Control\Session Manager键下的CriticalSectionTimeout关键字中。默认的值为2592000s,大约30天。我们可以通过改动这个值来调整超时时间,由于该值是系统公用的,所以建议设置该值时最小不要小于3S,以免影响到系统正常等待关键代码段超过3S的线程和其他应用。具体操作关键代码段的API,在MSDN中都有详细描述,这里也不进行复述。 下面简单讨论一下线程同步实现的原理:

操作系统之所以能够进行线程同步,主要依靠的是原子操作,原子操作是不会被打断的操作,通常它是由处理器体系结构提供,一般是由硬件支持的test-and-set操作。下面是笔者在X86体系架构下,效仿LINUX写的两个WINDOWS函数,TestAndSetBit()用于将指定的位设为1和TestAndClearBit()用于将指定的位清0,即加锁与解锁操作。

static int TestAndSetBit(int nOrder,volatile void* Var)

{

int nOldBit=0;

_asm {

MOV EAX,Var

MOV EBX,nOrder

LOCK BTS [EAX],EBX

MOV EAX,nOldBit

SBB nOldBit,EAX

}

return nOldBit;

}

static int TestAndClearBit(int nOrder,volatile void* Var)

{

int nOldBit=0;

_asm {

MOV EAX,Var

MOV EBX,nOrder

LOCK BTR [EAX],EBX

MOV EAX,nOldBit

SBB nOldBit,EAX

}

return nOldBit;

}

(注:LOCK指令是锁总线,用于多处理器的情况。BTS是X86的test-and-set操作。BTR是X86的test-and-reset操作)

下面通过一段代码用上面的函数来实现线程同步:

DWORD g_dwLock=0;

while(TestAndSetBit(0,&g_dwLock))

Sleep(1000);

/*

要保护的代码

*/

TestAndClearBit(0,&g_dwLock);

这是一个用户模式下的线程同步的应用,冲突发生时,当前线程睡眠,以使获得锁的线程能够运行被保护的代码,并在运行结束后解锁。当等待线程睡醒并重新执行时,就会得到锁并进行后面的运行。在核心模式下,原理是一样的,只是在资源冲突时的处理方式不同。

具体编程时要用哪一种方式进行线程的同步还要看程序的具体需要,笔者这里就不列举了。最后,笔者要向大家道歉,文章写的有些乱,可能有些地方讲的不清楚,有些地方理解的不对,还望大家及时指出。

参考书目:

《Inside windows 2000》

《WINDOWS内核编程》

colorknight

2003/4/3

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有