win32下的几种同步机制

来源:互联网 发布:深入浅出node.js 在线 编辑:程序博客网 时间:2024/05/04 11:29

win32下的几种同步机制

http://blog.sina.com.cn/s/blog_492101c70100068w.html



    在操作系统教材中,关于同步机制的介绍是一个重要内容,下面我们来看一下。
同步机制跟多线程关系紧密,本文也是从经典作品《win32多线程程序设计》中摘录总结出来的。
 
1、Critical Sections(临界区)
是否核心对象:否
是否可以有名字:否
适用范围:单个进程
所用变量类型:CRITICAL_SECTION
初始化函数:InitializeCriticalSection()
等待函数:EnterCriticalSection()
离开函数:LeaveCriticalSection()
释放函数:DeleteCriticalSection()
需要注意的是,上面的Delete函数并非真正的释放对象,不要跟c++里面的delete混淆了。
缺陷:
——Enter和Leave操作必须在同一个进程中,并且这中间的程序要尽可能短,不够灵活。
——因为Critical Sections不是核心对象,因此系统无法获知当前在Critical Sections内的线程的生死。因此,如果那个线程在没有Delete Critical Sections前就死掉了,系统无法为其清除Critical Sections。
——不能有一个以上的Critical Sections被等待。
优点:
使用简单,效率较高。

2、Mutex
是否核心对象:是
是否可以有名字:是
适用范围:系统所有进程
所用变量类型:Handle
初始化函数:CreateMutex(), OpenMutex()
等待函数:WaitForSingleObject(), WaitForMultipleObjects(), MsgWaitForMultipleObjects()
离开函数:ReleaseMutex()
释放函数:CloseHandle()
注意:只要是核心对象,都可以用CloseHandle()将其释放,包括文件的handle。
说明:
如果一个拥有一个Mutex对象的线程结束前(死掉或正常结束)并没有释放该对象,那么所有等待该Mutex对象的线程的Wait函数都会返回一个值,用于指示哪个Mutex对象出了问题,以便进行相应处理。
Mutex的拥有权并非是那个创建它的线程,而是那个最后对它进行Wait操作并且尚未进行ReleaseMutex()操作的线程。
缺陷:
——效率较低,因为要进入核心态,然后再返回用户态。
——因为Wait函数的调用而可能会导致不可预知的状态变化,使用起来不够直观。
——只能被拥有它的那个线程释放。
——不能有一个以上的线程同时拥有同一个Mutex。
优点:
——可以跨进程使用。
——等待一个Mutex对象时可以指定一个超时时间。

3、Semaphore(信号量)
是否核心对象:是
是否可以有名字:是
适用范围:系统所有进程
所用变量类型:Handle
初始化函数:CreateSemaphore()
等待函数:WaitForSingleObject(), WaitForMultipleObjects(), MsgWaitForMultipleObjects()
离开函数:ReleaseSemaphore()
释放函数:CloseHandle()
说明:
Semaphore是站在一个更高的角度来解决资源同步问题的,它把同一种共享资源同等看待,而仅关心其量的问题。Mutex实际可以看作Semaphore的一种退化,或一种特例。
正是因为Semaphore机制将同一种资源同一化看待,因此它并没有Mutex中所谓“拥有权”的概念。可以同时有多个线程成功锁定一个Semaphore,一个线程也可以在释放一个Semaphore前多次成功锁定同一个Semaphore。
缺陷:
因为Wait函数的调用而可能会导致不可预知的状态变化,使用起来不够直观。
优点:
有一个量的含义,因此适合于对有量的含义的共享资源进行同步。

4、Event(事件)
是否核心对象:是
是否可以有名字:是
适用范围:系统所有进程
所用变量类型:Handle
初始化函数:CreateEvent()
状态控制函数:SetEvent(), ResetEvent(), PulseEvent()
等待函数:WaitForSingleObject(), WaitForMultipleObjects(), MsgWaitForMultipleObjects()
离开函数:ReleaseSemaphore()
释放函数:CloseHandle()
说明:
Event对象有两种:手动重置和自动重置
手动重置:当一个Event对象变成激发状态后,不会自动变成非激发状态,除非程序调用ResetEvent()
自动重置:当一个Event对象变成激发状态后,会自动变成非激发状态
缺陷:
激发状态不会被系统保存,因此会出现激发状态丢失的情况。
优点:
——相比之下,Event机制最灵活。它只有两种状态:激发、未激发。而且这两种状态完全由程序控制,而不会像Mutex或Semaphore那样因为Wait函数的调用而导致可能的不可预知的状态变化。
——适用于设计用户自己的同步机制。
 
5、Interlocked函数
相关函数:InterlockedIncrement(), InterlockedDecrement(), InterlockedExchange()
说明:
这是一种最简单的同步机制,它只是针对32位变量进行操作。没有提供等待功能,只是保证对某个32位变量的存取操作是“一个一个”进行的,而不会发生混乱。
 
 
 
【附】
——一个handle与其所对应的实体是不同的两个概念。前者是一个核心对象,是OS用于维护其对应实体信息的。而后者就是一个用户态的实体,比如一个线程,比如一个文件。
 
——线程创建完成之初,其对应的handle的引用计数是2,一个是线程创建者的引用,另外一个是该线程本身的引用。
 
——win32中,对象被激发的具体意义:
Thread:线程结束时
Process:进程结束时
Change Notifycation:一个特定目录发生特定变化时
Console Input:控制台输入缓冲区有数据可用时
Envet:完全受制于那三个函数
Mutex:没有被任何线程拥有时
Semaphore:当计数器的内容大于0时(也就是有资源可用时)