最近回顾了下多线程的一些概念,主要的是线程间的同步以及互斥,简单记录下。


基本概念

2个基本概念:

  1. 同步:按预定的先后次序进行运行。比如:A.B.C3个线程,A先运行,然后B,然后C。
  2. 互斥:某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

相关函数

关键区/临界区 CRITICAL_SECTION


初始化--进入--离开--销毁


初始化:InitializeCriticalSection


进入:EnterCriticalSection


离开:LeaveCriticalSection


销毁:DeleteCriticalSection



单进程内互斥最好。


线程所有权的概念,所以当前可进入临界区的线程可以多次进入该临界区,所以 不能做同步。



互斥量 Mutex


创建--等待对象--释放--关闭


创建:CreateMutex


等待对象:WaitForSingleObject


释放:ReleaseMutex


关闭:CloseHandle



可用于保证只有一个实例被执行,主要是互斥用。


有线程所有权,所以wait到的线程可以多次wait到,然后进入相关区域。


事件 Event


创建--set--等待--reset--关闭


创建:CreateEvent


set:SetEvent


等待:WaitForSingleObject


reset:ResetEvent 或者 在WaitForSingleObject后自动reset


关闭:CloseHandle



PulseEvent函数,蛮有趣的,作用是set后立即reset,相当于发射一个脉冲。


可以用作同步。如果设置了自动重置,那么wait之后,重置了,那就肯定无法再次进入。



信号量 Semaphore


创建--释放资源--等待--释放资源--关闭


创建:CreateSemaphore


释放资源:ReleaseSemaphore


等待:WaitForSingleObject


关闭:CloseHandle



如果当前资源计数足够,那么还可以等待到。注意: release的时候,释放数量不可超过设定的资源总数。


类似事件,没有资源就会卡在那儿。



比较分析


  1. 所有都可用于互斥
  2. Event和Semaphore可用于同步
  3. CriticalSection是非内核对象,相对更加高效
  4. 另外3个都是内核对象,可以跨进程,可用于保证只有一个实例运行
  5. 另外3个有对应的open函数
  6. Event可自动Reset,方便
  7. Semaphore可以指定资源数
  8. Mutex可以很好的处理“遗弃”问题,即进程结束未释放,会自动释放,对多进程同时使用一个名称的互斥量来说,这是一个好消息

以上,大家各有优缺点,使用时需要根据实际情况选择。