您的位置:首页 > 移动开发 > Objective-C

用内核对象同步线程

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
现在就来重点说下Event,waitable timer,Semaphore,Mutex.这四个用的比较多。
在说这四个内核对象之前先来说下能让线程进入等待状态的函数,也就是去等待上面四个内核对象的状态的函数。他们有
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
 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息