我需要同步访问Windows上的HANDLE吗

Do I need to synchronize access to a HANDLE on Windows?

本文关键字:上的 HANDLE Windows 访问 同步      更新时间:2023-10-16

我有一个可等待计时器的HANDLE,它可以在我的Windows服务中的许多正在运行的线程之间共享,用于API,如CreateWaitableTimer、WaitForSingleObject、SetWaitableTimer和CancelWaiableTimer。

我的问题是,我是否需要通过互斥或关键部分同步对此HANDLE本身的访问(读/写)?

编辑: 好的,我想我需要澄清(用代码):

//Say, I have a global handle
HANDLE ghWaitableTimer = NULL;      //Originally set to NULL
...
//Thread one
if(!ghWaitableTimer)
{
    ghWaitableTimer = ::CreateWaitableTimer(NULL, FALSE, NULL);
}
...
//Thread two
if(ghWaitableTimer)
{
    ::SetWaitableTimer(ghWaitableTimer, &liWhen, 0, NULL, NULL, FALSE);
}
...
//Thread three
if(ghWaitableTimer)
{
    ::WaitForSingleObject(ghWaitableTimer, INFINITE);
}

或者我需要这样做吗:

//Say, I have a global handle
HANDLE ghWaitableTimer = NULL;      //Originally set to NULL
CRITICAL_SECTION CriticalSection;   //Must be initialized before it's used
...
//Thread one
::EnterCriticalSection(&CriticalSection);
if(!ghWaitableTimer)
{
    ghWaitableTimer = ::CreateWaitableTimer(NULL, FALSE, NULL);
}
::LeaveCriticalSection(&CriticalSection);
...
//Thread two
::EnterCriticalSection(&CriticalSection);
HANDLE hTimer = ghWaitableTimer;
::LeaveCriticalSection(&CriticalSection);
if(hTimer)
{
    ::SetWaitableTimer(hTimer, &liWhen, 0, NULL, NULL, FALSE);
}
...
//Thread three
::EnterCriticalSection(&CriticalSection);
HANDLE hTimer = ghWaitableTimer;
::LeaveCriticalSection(&CriticalSection);
if(hTimer)
{
    ::WaitForSingleObject(hTimer, INFINITE);
}

如果全局变量的值可能发生更改,则只需要同步即可从多个线程读取该全局变量。如果您正在创建一个计时器对象,并且句柄的值在此之后再也不会更改,则不需要同步来读取其值。

使用可等待计时器,即在给定计时器句柄的情况下启动计时器并等待该句柄触发,不需要互斥等支持。

从描述中可以清楚地看出,它是专门为线程间操作而设计的,例如,另一个线程可以使用WaitForSingleObject来等待触发计时器事件等。
如果有必要使用互斥锁来保护它,则上述用例
根本不可能,相反,投票是必要的。

如果这还不够推理,这里是页面同步对象的第一句话:

同步对象是一个对象,其句柄可以在一个等待函数,用于协调多个螺纹。

上述页面的子类别包括Mutex、Semaphore、
等待计时器;一切都在同一水平上。

然而,正如第一句所述,我刚才所说的仅适用于使用它。这些操作的共同点是,您已经有了一个计时器句柄(该句柄不会因上述操作而更改)创建一个新的定时器句柄并将其分配给变量确实会更改变量值。。。

因此,您基本上有两个问题:
1) 如果线程2在线程1创建计时器之前启动计时器,你认为会发生什么?如果在启动Visual Studio之前在Visual Studio中键入一些文本,会发生什么情况?对
2) 句柄只是一个数字ID,可以随意复制和移动。即使在创建之后,计时器也无法保护自己的句柄。在使用过程中对手柄进行任何更改都是不好的。

为此,互斥锁也不是解决方案。它可以保护定时器句柄,但谁来保护互斥句柄。。。?正确的任何同步机制都依赖于在用于同步任何内容之前准备

问题的真正解决方案是在启动任何线程之前创建计时器并将其分配给句柄;然后将句柄提供给启动的线程(参数或全局变量等)