用内核对象同步线程
2007-03-01 03:33
441 查看
用户方式同步具有速度快的优点。但是它的缺点特是显而易见的。
首先,用互锁函数家族的时候,这些函数只能用在单值数据上
如果用关键代码段的话,只能对单个进程中的线程进行同步。而且容易出现死琐,而且不能设置等待时间
那么内核对象就克服了用户方式同步的几个缺点,能够在不同进程间对线程实施同步,而且处理完全不止在单值数据上。但是内核方式同步线程时,必须将线程进入到内核方式,这样就使处理速度大大降低。这也是内核方式的缺点,所以还是能用用户方式处理的就用用户方式来处理。
现在来说下一个很多内核对象都具有的特性,这就是signaled/nonsignaled特性。
这个特性是这样的:在内核对象处于运行状态时,他就是nonsignaled状态,当内核对象运行结束时,就会处于signaled状态。在内核对象中是用一个bool值来表示的。所以查看内核对象的状态很容易。只要查这个值就可以了。所以当线程要等待的内核对象处于signaled状态时,那么这个线程就可以被CPU调度,否则处于等待状态。
拥有这个特性的内核对象有:
· Processes | · File change notifications |
· Threads | · Events |
· Jobs | · Waitable timers |
· Files | · Semaphores |
· Console input | · Mutexes |
在说这四个内核对象之前先来说下能让线程进入等待状态的函数,也就是去等待上面四个内核对象的状态的函数。他们有
DWORD WaitForSingleObject(HANDLE hObject,DWORD dwMillisecounds)
参数:
第1个参数就是要等待的对象的HANDLE,可以是上面四个中的一个。
第2个参数是等待超时时间。
返回值
WAIT_OBJECT_0//成功等待。也就是内核对象已经为signaled,线程成为可调度线程
WAIT_TIMEOUT//因为超时,线程重新唤醒,成为可调度的
WAIT_FAILED//将一个错误的值传递给WaitForSingleObject,比如传递了一个无效句柄。
DWORD WaitForMultipleObjects(DWORD dwCount,CONST HANDLE *phObjects,BOOL fWaitAll,DWORD dwMillisecounds)
参数:
dwCount //想要让函数查看的内核对象的数目,这个值必须在1到MAXIMUN_WAIT_OBJECTS(64)
phObjects //指向内核对象句柄的数组的指针
fWaitAll //如果为TRUE,就是等待到所有内核对象都signaled。FALSE则是只要有一个signaled就唤醒
dwMillisecounds //超时时间
返回值:
和WaitForSingleObject一样。只是,如果fWaitAll==false。那么如果想得到哪个对象signaled就可以将返回值剪去WAIT_OBJECT_0。(前提是,返回值即不是WAIT_TIMEOUT也不是WAIT_FAILED)
其实再调用上面两个函数时,如果等待成功(就是返回值为WAIT_OBJECT_0),会对内核对象产生一个副作用。有的内核对象的副作用就是改变的内核对象的状态(比如自动清楚内核对象)。有的内核对象则没有任何副作用(比如线程,进程内核对象)。
下面就来逐一介绍Event,Waitable timer,Semaphrone,Mutex对象
先是Event对象。Event对象是最基本的内核对象。它包括:
1. 使用计数器
2. 自动重置/人工重置开关
3. signaled/nonsignal开关
1,3不用多介绍。 重点说下2。什么叫自动重置?就是所有等待的线程,当Event对象变成signaled状态时,只会随即的挑选一个线程进入可调度状态。然后Event对象会被自动置为nonsignaled状态。而人工重置是当Event对象变成signaled时候,所有等待的线程都会被置为可调度状态。CPU会给他们都分配时间片。而且不会自动将Event状态置为nonsignaled。要通过ResetEvent将Event变为nonsignaled。
至于创建Event内核对象CreateEvent函数,可以查找MSDN。
然后就是WaitableTimer内核对象。
CreateWaitableTimer OpenWaitableTimer的使用可以查找MSDN。重点说下设置WaitableTimer
设置WaitableTimer使用SetWaitbaleTimer。原形如下:
BOOL SetWaitableTimer(
HANDLE hTimer, // handle to a timer object
const LARGE_INTEGER *pDueTime, // when timer will become signaled
LONG lPeriod, // periodic timer interval
PTIMERAPCROUTINE pfnCompletionRoutine, // pointer to the completion routine
LPVOID lpArgToCompletionRoutine, // data passed to the completion routine
BOOL fResume // flag for resume state
);
参数:
*pDueTime是等待定时器第1次报时的时间。可以为这个参数传递0,表示调用函数的时候就报时。或者传递一个负值,表示调用这个函数开始延迟n*100ns后开始第1次报时。
pfnCompletionRoutine指向一个函数的地址。如果这项不为NULL,那么当定时器报时的时候,会讲这个函数放入线程的APC队列。(什么是APC会在以后详细介绍)
下面再来说下 Semaphore。
Semaphroe的作用是为一个资源计数,而这个资源又是多个的。比如说你想对一个拥有10个元素的数组进行同步。那么就可以用Semaphore。当10个元素都被占用的时候。Semaphore就处于nonsignaled状态,反之,有元素可以被处理的时候就处于nignaled状态。
Semapore包括:
1. 使用计数器
2. 最大资源数量
3. 当前可使用资源数量
他的使用规则是:
1. 当前资源大于0,发出信标信号(处于signaled状态)
2. 当前资源等于0,不发出信号
3. 0<=当前资源<=最大资源
CreateSemaphore OpenSemaphore ReleaseSemaphore可以查看MSDN
ReleaseSemaphore是将Semaphore的可使用资源进行增加。
最后就是Mutex了。Mutex是使用的最多的线程同步内核对象。它的作用是保证线程对单个资源的互斥访问权。它包括:
使用计数器
拥有Mutex的线程ID
递归计数器//该线程拥有互斥对象的次数
Mutex的使用规则是:
线程ID为0,互斥对象不被任何线程所拥有,并且发出该互斥对象的通知信号
线程ID不为0,那么线程就拥有该互斥对象,不发出通知信号
CreateMutx OpenMutex ReleaseMutex查看MSDN
下面是互斥对象与关键代码段的比较
[align=center]Characteristic[/align] | [align=center]Mutex[/align] | [align=center]Critical Section[/align] |
Performance | Slow | Fast |
Can be used across process boundaries | Yes | No |
Declaration | HANDLE hmtx; | CRITICAL_SECTION cs; |
Initialization | hmtx= CreateMutex (NULL, FALSE, NULL); | InitializeCriticalSection(&cs); |
Cleanup | CloseHandle(hmtx); | DeleteCriticalSection(&cs); |
Infinite wait | WaitForSingleObject (hmtx, INFINITE); | EnterCriticalSection(&cs); |
0 wait | WaitForSingleObject (hmtx, 0); | TryEnterCriticalSection(&cs); |
Arbitrary wait | WaitForSingleObject (hmtx, dwMilliseconds); | Not possible |
Release | ReleaseMutex(hmtx); | LeaveCriticalSection(&cs); |
Can be waited on with other kernel objects | Yes (use WaitForMultipleObjects or similar function) | No |
相关文章推荐
- 第九章 线程与内核对象的同步(1)
- Windows编程--线程和内核对象的同步-信标(信号量)内核对象
- 利用内核对象同步线程
- 第九章 线程与内核对象的同步(2)
- Windows编程-- 线程和内核对象的同步 - 互斥对象内核对象
- 利用内核对象同步线程
- windows核心编程之线程内核对象同步(1)
- Windows核心编程 第九章 线程与内核对象的同步(下)
- 第九章 线程与内核对象的同步(3)
- 《Windows核心编程》读书笔记(六) 第9章 线程与内核对象的同步
- windows核心编程之线程内核对象同步(2)
- 第9章 线程与内核对象的同步
- 线程与事件内核对象的同步
- 第九章 线程与内核对象的同步(4)
- Windows编程-- 线程和内核对象的同步 - 互斥对象内核对象
- Windows编程那些事----线程与内核对象同步之【信标对象】
- 线程与内核对象的同步
- Windows核心编程 第九章 线程与内核对象的同步(上)
- 第九章 线程与内核对象的同步(5)
- Windows编程--线程和内核对象的同步-事件内核对象