Windows中多线程的同步
windows进程间同步方式有:1. 互斥量 mutex 2. 信号量 semaphore 3.事件 event 4.临界区 Critical Section 5.互锁函数
临界区和互锁函数没有相应的内核对象因而不能跨进程
1. 临界区
只能同步同一个进程的线程之间的同步,因为临界区不能跨越进程的边界工作。也是因为临界区没有name,所以不能跨进程使用。
访问临界区之前进行锁定,访问后进行解锁。
如果进程B访问进程A锁定的临界区,那么进程B会被阻塞,直到线程A释放临界区,线程B才可以运行。在线程B进行阻塞期间,不占用CPU时间.
2. 互斥量
可以同步在相同进程,或不同进程间的线程进行同步。所以互斥量是有name的,可以跨进程使用。
互斥量与临界区的区别,如果一个线程锁定了临界区,而终止时没有解除临界区的锁定,那么等待临界区空闲的其他线程将无限期的阻塞下去。然而,如果锁定互斥量的线程不能在其终止前解除互斥量的锁定,那么系统将认为互斥量被“放弃”了并自动释放该互斥量,这样等待进程就可以继续执行了。
3. 事件
在任何特定时间,事件只能处在两种状态的一种:引发(设置)或者调低(重置)。设置可以任务是出于信号状态,重置事件可以认为是出于非信号状态。
事件也被描述为“线程触发器”。事件也不能跨进程。同样它没有name。
事件有自动设置事件和手动设置事件。其差别是当自动设置事件上阻塞的线程被唤醒时,该事件别自动设置为信号状态。手动设置事件不能自动重置,它必须使用编程的方式重置。
l 如果事件只触发一个线程,那么使用自动设置事件和使用SetEvent唤醒等待线程。
这里不需要调用ResetEvent,因为线程被唤醒的那一刻事件将被自动重置。
l 如果事件将触发两个或者多个线程,那么使用手动设置线程和使用PulseEvent唤醒所以的等待线程。而且,您不需要调用ResetEvent,因为PluseEvent在唤醒所有等待线程后为你重置事件。
4. 信号量
首先,信号量可以同步不同进程,相同进程中的线程。
其次,信号量跟其他3种同步机制不同的是,上面3种的同步机制的特性“要没有,要么没有”,信号量则不同,它始终代表可用资源的数量。锁定信号量会减少资源数,释放信号量则增加资源数。只有在资源数为0的时候,线程才会被阻塞。
5. 互锁函数
如何保证我们再修改某块内存的
同时,不让任何其他进程/线程修改呢?在Direct内,比如在创建VertexBuffer
时,有Locked和Unlocked函数来保证目标内存同一时刻有唯一的进程/线程访问。
就是要把该片内存先锁定(锁死), 然后再进行修改,然后再解锁。
Windows还为我们提供了互锁函数来保证对单个变量的递增或递减是同一时刻唯一的。
它们是InterlockedExchangeAdd等函数。