进程间通信简单的说有三个问题,第一个问题是:一个进程如何把信息传递给另一个,第二个问题是:要确保两个或者更多的进程在互动中不会出现交叉(即是进程互斥问题),第三个问题是:进程间同步问题、
四种进程或者线程同步互斥的控制方法
1):临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
2):互斥量:为协调共同对一个共享资源的单独访问而设计的
3):信号量:为控制一个具有有限数量用户资源而设计
4):事件:用来通知线程有一些事件已发生,从而启动后继任务的开始。
临界区(Critical Section)
保证在某一时刻只有一个线程能访问数据的简便办法,在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开,临界区在被释放后,其他线程可以继续抢占,并以此达到原子方式操作共享资源的目的。
临界区包含两个操作原语:
EnterCriticalSection() 进入临界区
LeaveCriticalSection() 离开临界区
虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。
互斥量(Mutex)
互斥量跟临界区很相似,只有拥有互斥量对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其它线程在获得以访问资源,互斥量比临界区复杂。使用互斥量不仅仅可以在同一进程的不同线程中实现资源的共享,而且还可以在不同进程的线程之间实现对资源的安全访问。
互斥量包含的几个操作原语:
CreateMutex() 创建一个互斥量
OpenMutex() 打开一个互斥量
ReleaseMutex() 释放互斥量
WaitForMultipleObjects() 等待互斥量对象
信号量(Semaphores)
信号量对象对线程的同步方式与上面的两种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的pv操作相同,它指出了同时访问共享资源的线程最大数目,它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。在用CreateSemaphone()创建信号量时既要同时指出允许的最大资源计数和当前可用资源计数,一般是将挡墙可用资源计数设置为最大资源计数,每增加一个线程对共享资源的访问,当前可用资源计数就会减去1,只要当前可用资源计数是大于0,就可以发出信号量信号,但是当前可用计数减小到0则说明当前占用资源的线程数已经达到了所允许的最大数目,不能再允许其他线程的进入,此时的信号量将无法发出,线程在处理完共享资源后,应在离开的同时通过ReleaseSemaphone()函数将当前可用资源计数加1,在任何时候当前可用资源计数决不能大于最大资源计数。
信号量S是一个整数,S大于等于零时代表可供并发进程使用的资源实体数,但s小于零时则表示正在等待使用共享资源的进程数。
p操作申请资源:
1)s减去1
2)若s减1仍大于0,则进程继续执行。
3)若s减1小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转入进程调度。
V操作释放资源
1)s加1
2)若相加结果大于零,则进程继续执行。
3)若相加结果小于等于零,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转入进程调度、
信号量包含的几个操作原语:
CreateSemaphore() 创建一个信号量
OpenSemaphore() 打开一个信号量
ReleaseSemaphore() 释放信号量
WaitForSingleObject() 等待信号量
事件(Event)
事件对象也可以通过通知操作的方式来保持线程的同步。并且可以实现不同进程中的线程同步操作。
信号量包含的几个操作原语:
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
信号量是一种解决进程同步的解决方案,同时信号量也可以当做互斥量来使用,使用信号量来解决进程同步问题是编程中使用较多的方法。