标签:
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。
内核模式下的方法有:事件,信号量,互斥量。
保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么 在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操 作共享资源的目的。 仅能在同一进程内使用
互斥量跟临界区很相似,只有拥有互斥对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。
信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源 ,这与操作系统中的PV操作相同。
事件机制,则允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务。
以上几种方法在win和linux下的API又有不同
如同进程一样,线程也可以通过信号量来实现通信,虽然是轻量级的。信号量函数的名字都以"sem_"打头。线程使用的基本信号量函数有四个。
互斥锁不同,条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。条件变量分为两部分: 条件和变量。条件本身是由互斥量保护的。线程在改变条件状态前先要锁住互斥量。条件变量使我们可以睡眠等待某种条件出现。条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。条件的检测是在互斥锁的保护下进行的。如果一个条件为假,一个线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程,重新获得互斥锁,重新评价条件。如果两进程共享可读写的内存,条件变量可以被用来实现这两进程间的线程同步。
EnterCriticalSection() 进入临界区
LeaveCriticalSection() 离开临界区
CreateMutex() 创建一个互斥量
OpenMutex() 打开一个互斥量
ReleaseMutex() 释放互斥量
WaitForMultipleObjects() 等待互斥量对象
CreateSemaphore() 创建一个信号量
OpenSemaphore() 打开一个信号量
ReleaseSemaphore() 释放信号量
WaitForSingleObject() 等待信号量
CreateEvent() 创建一个事件
OpenEvent() 打开一个事件
SetEvent() 回置事件
WaitForSingleObject() 等待一个事件
WaitForMultipleObjects() 等待多个事件
|
Mutex |
Critical Section |
性能和速度 |
慢。 Mutex 是内核对象,相关函数的执行 (WaitForSingleObject, ReleaseMutex)需要用户模式(User Mode)到内核模式 (Kernel Mode)的转换,在x86处理器上这种转化一般要 发费600个左右的 CPU指令周期。 |
快。 Critical Section本身不是内核对象,相关函数 (EnterCriticalSection,LeaveCriticalSection) 的调用一般都在用户模式内执行,在x86处理器上 一般只需要发费9个左右的 CPU指令周期。只有 当想要获得的锁正好被别的线程拥有时才会退化 成和Mutex一样,即转换到内核模式,发费600个 左右的 CPU指令周期。 |
能否跨越进程(Process)边界 |
可以 |
不可 |
定义写法 |
HANDLE hmtx; |
CRITICAL_SECTION cs; |
初始化写法 |
hmtx= CreateMutex (NULL, FALSE, NULL); |
InitializeCriticalSection(&cs); |
结束清除写法 |
CloseHandle(hmtx); |
DeleteCriticalSection(&cs); |
无限期等待的写法 |
WaitForSingleObject (hmtx, INFINITE); |
EnterCriticalSection(&cs); |
0等待(状态检测)的写法 |
WaitForSingleObject (hmtx, 0); |
TryEnterCriticalSection(&cs); |
任意时间等待的写法 |
WaitForSingleObject (hmtx, dwMilliseconds); |
不支持 |
锁释放的写法 |
ReleaseMutex(hmtx); |
LeaveCriticalSection(&cs); |
能否被一道用于等待其他内核对象 |
可以(使用WaitForMultipleObjects, WaitForMultipleObjectsEx, MsgWaitForMultipleObjects, MsgWaitForMultipleObjectsEx等等) |
不可 |
当拥有锁的线程死亡时 |
Mutex变成abandoned状态,其他的等待线程可以获得锁。 |
Critical Section的状态不可知(undefined), 以后的动作就不能保证了。 |
自己会不会锁住自己 |
不会(对已获得的Mutex,重复调用WaitForSingleObject不会 锁住自己。但最后你别忘了要调用同样次数的 ReleaseMutex) |
不会(对已获得的Critical Section,重复调用 EnterCriticalSection不会锁住自己。但最后 你别忘了要调用同样次数的 LeaveCriticalSection) |
标签:
原文地址:http://www.cnblogs.com/raichen/p/5768752.html