2015年11月12日 wanglinqiang整理html
保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只容许一个线程对共享资源进行访问。若是有多个线程试图同时访问临界区,那么在有一个线程进入后其余全部试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其余线程能够继续抢占,并以此达到用原子方式操 做共享资源的目的。数据库
临界区包含两个操做原语:数组
EnterCriticalSection() // 进入临界区 LeaveCriticalSection() // 离开临界区
EnterCriticalSection()语句执行后代码将进入临界区之后不管发生什么,必须确保与之匹配的 LeaveCriticalSection()都可以被执行到。不然临界区保护的共享资源将永远不会被释放。虽然临界区同步速度很快,但却只能用来同步本 进程内的线程,而不可用来同步多个进程中的线程。安全
MFC提供了不少功能完备的类,我用MFC实现了临界区。MFC为临界区提供有一个 CCriticalSection类,使用该类进行线程同步处理是 很是简单的。只需在线程函数中用CCriticalSection类成员函数Lock()和UnLock()标定出被保护代码片断便可。Lock()后代 码用到的资源自动被视为临界区内的资源被保护。UnLock后别的线程才能访问这些资源。多线程
互斥量跟临界区很类似,只有拥有互斥对象的线程才具备访问资源的权限,因为互斥对象只有一个,所以就决定了任何状况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其余线程在得到后得以访问资源。互斥量比临界区复杂。由于使用互斥不只仅可以在同一应用程序不一样线程中实现资源的安全共享,并且能够在不一样应用程序的线程之间实现对资源的安全共享。
互斥量包含的几个操做原语:并发
CreateMutex() // 建立一个互斥量 OpenMutex() // 打开一个互斥量 ReleaseMutex() // 释放互斥量 WaitForMultipleObjects() // 等待互斥量对象
一样MFC为互斥量提供有一个CMutex类。使用CMutex类实现互斥量操做很是简单,可是要特别注意对CMutex的构造函数的调用函数
CMutex( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL)
不用的参数不能乱填,乱填会出现一些意想不到的运行结果。操作系统
信号量对象对线程的同步方式与前面几种方法不一样,信号容许多个线程同时使用共享资源 ,这与操做系统中的PV操做相同。它指出了同时访问共享 资源的线程 最大数目。它容许多个线程在同一时刻访问同一资源,可是须要限制在同一时刻访问此资源的最大线程数目。在用CreateSemaphore()建立信号量 时即要同时指出容许的最大资源计数和当前可用资源计数。通常是将当前可用资源计数设置为最大资源计数,每增长一个线程对共享资源的访问,当前可用资源计数 就会减1,只要当前可用资源计数是大于0的,就能够发出信号量信号。可是当前可用计数减少到0时则说明当前占用资源的线程数已经达到了所容许的最大数目, 不能在容许其余线程的进入,此时的信号量信号将没法发出。线程在处理完共享资源后,应在离开的同时经过ReleaseSemaphore()函数将当前可 用资源计数加1。在任什么时候候当前可用资源计数决不可能大于最大资源计数。线程
PV操做及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。信号量S是一个整数,S大于等于零时表明可供并发进程使用的资源实体数,但S小于零时则表示正在等待使用共享资源的进程数。
P操做 申请资源:设计
(1) S减1;
(2) 若S减1后仍大于等于零,则进程继续执行;
(3) 若S减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,而后转入进程调度。
V操做 释放资源:
(1) S加1;
(2) 若相加结果大于零,则进程继续执行;
(3) 若相加结果小于等于零,则从该信号的等待队列中唤醒一个等待进程,而后再返回原进程继续执行或转入进程调度。
信号量包含的几个操做原语:
CreateSemaphore() // 建立一个信号量 OpenSemaphore() // 打开一个信号量 ReleaseSemaphore() // 释放信号量 WaitForSingleObject() // 等待信号量
事件对象也能够经过通知操做的方式来保持线程的同步。而且能够实现不一样进程中的线程同步操做。
信号量包含的几个操做原语:
CreateEvent() // 建立一个事件 OpenEvent() // 打开一个事件 SetEvent() // 回置事件 WaitForSingleObject() // 等待一个事件 WaitForMultipleObjects() // 等待多个事件
WaitForMultipleObjects 函数原型:
WaitForMultipleObjects( IN DWORD nCount, // 等待句柄数 IN CONST HANDLE *lpHandles, // 指向句柄数组 IN BOOL bWaitAll, // 是否彻底等待标志 IN DWORD dwMilliseconds // 等待时间 )
参数nCount指定了要等待的内核对象的数目,存放这些内核对象的数组由lpHandles来指向。fWaitAll对指定的这nCount个内核对象的两种等待方式进行了指定,为TRUE时当全部对象都被通知时函数才会返回,为FALSE则只要其中任何一个获得通知就能够返回。 dwMilliseconds在这里的做用与在WaitForSingleObject()中的做用是彻底一致的。若是等待超时,函数将返回 WAIT_TIMEOUT。
关于更详细的一篇介绍,请看这里:
http://www.cppblog.com/killsound/archive/2009/07/15/16147.html