Marvin's Blog【程式人生】

Ability will never catch up with the demand for it

15 Feb 2020

Win32文档学习笔记(一):关于同步

Win32文档学习笔记:Synchronization/About Synchronization

Wait Functions

Wait函数可以让当前线程挂起,直到所需要的条件满足,或者超时。不同的Wait函数,代办不同的等待条件。

单目标(Single-Object)Wait函数包括:SignalObjectAndWait, WaitForSingleObject以及WaitForSingleObjectEx。

多目标(Multi-Object)Wait函数包括:WaitForMultipleObjects(Ex), MsgWaitForMultipleObjects(Ex)。多目标情况下,可以等待任意一个目标的条件满足,或者所有目标的条件都满足。如果是前者,那么在有多个目标条件成熟的时候,只返回第一个目标;如果是后者,那么在等待的过程中,其目标的状态是可以被其他线程改变的,知道所有目标的条件都满足时,这些目标才归属于调用者。

可变更(altertable)Wait函数包括:MsgWaitForMultipleObjectsEx, SingleObjectAndWait, WaitForMultipleObjectsEx以及WaitForSingleObjectEx,在系统触发某些IO事件的时候会中止等待并返回。

RegisterWaitForSingleObject在目标条件满足的时候可以从线程池启动线程执行任务。UnregisterWaitEx用来取消注册。

WaitOnAddress可以用来等待某个内存地址上的值发生变化。其配套函数包括:WakeByAddressSingle 和WakeByAddressAll。

Wait函数的超时定时器的精度取决于系统时钟。系统时钟的嘀嗒(tick)是固定频率的。使用timeGetDevCaps 可以检查系统时钟的最大精度,通过timeBeginPeriod 可以设置系统时钟的精度,通过timeEndPeriod可以重设精度。这些函数使用不当会对系统系统造成影响。

Wait函数会修改一些目标同步对象的状态。修改只会发生才Wait函数即将返回之前。可被修改状态的目标包括:

  • semaphore,计数器会减一
  • mutex, auto-reset event以及change-notification,其状态会被设置为nonsignaled
  • synchronization timer,设置成nonsignaled

manual-reset event、manual-reset timer、进程、线程以及控制台输入作为目标对象的时候不受影响。

如果线程创建了窗口,那么这个线程就要处理窗口事件循环。窗口事件是广播给系统所有窗口的。如果一个线程创建有窗口,然后使用wait函数来无期限等待,系统将会死锁。使用MsgWaitForMultipleObjects或者MsgWaitForMultipleObjectsEx来避免死锁。

Synchronization Objects

同步对象可作为Wait函数的目标。向系统请求这些同步对象的时候,会获得这些对象的控把(handle)。可以在不同的进程获取同一的对象的控把。

同步对象包括以下类型:

  • Event
  • Mutex
  • Semaphore
  • Waitable Timer

下面这些对象也可以兼用于同步:

  • Change notification
  • Console input
  • Job
  • Memory resource notification
  • Process
  • Thread

在某些情况下,可以使用文件、署名管道、或者可通信设备作为同步对象。不过不推荐使用这些做同步用。一个替代的办法是使用异步I/O以及OVERLAPPED的事件对象。

Event Objects

事件对象,其通告状态可以通过SetEvent修改。有两类:

  • Manual-reset event,通告之后状态需要手动通过ResetEvent来设置成未通告状态。通告会免除任意数目的等待中的线程或者后来的线程的等待。
  • Auto-reset event,初始处于未通告状态,通告会只会导致某一个线程免除等待。

使用CreateEvent(Ex)可以创建事件对象;使用OpenEvent可以打开其他进程的事件对象。

Mutex Objects

互斥对象,只能被一个线程持有,其他申请持有的线程将等待。

互斥对象可以署名,或者不署名。使用CreateMutex(Ex)可以创建互斥对象。可通过OpenMutext或DuplicateHandle(父子对象间使用)来获取其他线程的互斥对象。ReleaseMutex放弃对互斥对象的持有。

一个线程可以多次等待其持有的互斥变量而不会挂起。当是调用ReleaseMutex 的次数应和等待的次数一样,才能放弃持有。

线程在退出时还持有互斥对象的话,该互斥对象被抛弃。等待中的其他线程可以获取被抛弃的互斥对象,但是等待函数会返回WAIT_ABANDONED。

critical section objects 和互斥对象功能类似,但只能用于一个进程。

Semaphore Objects

Waitable Timer Objects

….

Synchronization Object Security and Access Rights

Windows的安全模型可应用于事件、互斥、信号量、可候计时等对象的访问控制;不可应用于Timer queue、interlocked variables、critical section objects。

在创建的时候可在一定安全描述符,如果不指定则默认的ACLs来自创建着的primary或者impersonation token。

获取和设置安全描述符:GetNamedSecurityInfo, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo。

Create系列函数对同步对象拥有完全的访问权限,Open类函数则需要检查ACLs。

章节的剩余部分对ACLs的权限有更详细的描述。

(待补充)

comments powered by Disqus