线程同步对象之可等待定时器
线程同步对象之可等待定时器
——每周杂谈 第003篇
作者:Tocy 时间:2012-05-26
同步对象(synchronization object)是指其句柄能够被wait函数族(例如 WaitForSingleObject函数)使用,并用于控制多线程执行的对象。通常有以下几个同步对象:
表格 1 同步对象类型
类型 |
描述 |
Event 事件 |
通知一个或者多个线程某个事件发生,Event Objects. |
Mutex 互斥量 |
同一时间只能被一个线程获得,保证线程用于对共享资源互斥性访问,Mutex Objects. |
Semaphore 信号量 |
保持[0, maximum]范围内的一个数值,可以限制同时访问共享资源的线程数量,Semaphore Objects. |
Waitable timer 可等待计时器 |
在设定的时间间隔到达时通知一个或者多个线程,Waitable Timer Objects. |
相信对于多数人,事件、互斥量和信号量都是非常熟悉的,这里着重介绍下可等待计时器。如果想了解前三个同步对象的使用,请参考MSDN或者其他文章。
同步对象亦可用于多进程之间的通信(IPC)。
当约定的时间到达,可等待计时器(Waitable timer)的状态会被设置成signaled(已通知状态,或触法状态)。Windows下可等待计时器有以下几种:
表格 2 等待计时器类型
对象 |
说明 |
Manual-reset timer 手工重置计时器 |
计时器会保持signaled,除非调用SetWaitableTimer新建一个约定时间。 |
Synchronization timer 同步计时器 |
计时器在线程完成wait操作之前保持singled,也就是说计时器的状态重置是在wait函数操作完成之后进行的。 |
Periodic timer 周期性计时器 |
按照指定的周期重新激活计时器,除非计时器被重置或者取消。周期性计时器可以是以上两种类型的任意一种。 |
在MSDN(http://msdn.microsoft.com/en-us/library/ms687012(v=vs.85))中,针对移动设备不推荐使用周期性计时器,尤其是高频率的(低时间间隔)的周期性计时器。推荐优先使用非周期计时器,或者将计时器周期设置为不小于1秒。
可等待计时器用法跟事件、互斥量、信号量等同步对象类似,首先创建计时器(使用 CreateWaitableTimer or CreateWaitableTimerEx 函数),在其他进程中可以使用OpenWaitableTimer函数来打开一个存在的计时器(使用该计时器的名字即可)。所用拥有计时器句柄的线程都可以使用wait函数族来等待该其状态改变。使用 SetWaitableTimer函数来激活计时器。使用CancelWaitableTimer函数可以将计时器置位(non-signaled),重置计时器调用SetWaitableTimer函数。当不再使用计时器对象时,使用CloseHandler来关闭即使句柄既可以。
说明:
1. CreateWaitableTimer函数可以决定计时器类型(手中重置或者同步计时器)。
函数原型:
HANDLE WINAPI CreateWaitableTimer(
__in_opt LPSECURITY_ATTRIBUTES lpTimerAttributes,
__in BOOL bManualReset, // 这个参数决定计时器类型
__in_opt LPCTSTR lpTimerName
);
返回值:函数成功则返回计时器对象句柄,失败则返回NULL。
2. SetWaitableTimer函数可以激活特定可等待计时器,原型如下:
BOOL WINAPI SetWaitableTimer(
__in HANDLE hTimer, // 计时器句柄
__in const LARGE_INTEGER *pDueTime, // 计时器状态改变的等待时间
__in LONG lPeriod, // 周期性计时器的周期
__in_opt PTIMERAPCROUTINE pfnCompletionRoutine,
__in_opt LPVOID lpArgToCompletionRoutine,
__in BOOL fResume
);
详细参数意义:http://msdn.microsoft.com/en-us/library/ms686289(v=vs.85)
下面是MSDN中给出的实例代码:
#include <windows.h>
#include <stdio.h>
int main()
{
HANDLE hTimer = NULL;
LARGE_INTEGER liDueTime; // 以100纳秒为分割
liDueTime.QuadPart = -100000000LL;
// Create an unnamed waitable timer.
hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
if (NULL == hTimer)
{
printf("CreateWaitableTimer failed (%d)\n", GetLastError());
return 1;
}
printf("Waiting for 10 seconds...\n");
// Set a timer to wait for 10 seconds.
if (!SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0))
{
printf("SetWaitableTimer failed (%d)\n", GetLastError());
return 2;
}
// Wait for the timer.
if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0)
printf("WaitForSingleObject failed (%d)\n", GetLastError());
else printf("Timer was signaled.\n");
return 0;
}
注:版权所有,请勿用于商业用途,转载请注明原文地址。本人保留所有权利。
----------------------------------------------------------------------------------------------------------------------------
本文作者:Tocy e-mail: zyvj@qq.com
版权所有@2015-2020,请勿用于商业用途,转载请注明原文地址。本人保留所有权利。