线程同步与互斥的总结

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


基本概念

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

跨进程,set后就一直可以等待到,reset后就等待不到了。有一个 PulseEvent函数,蛮有趣的,作用是set后立即reset,相当于发射一个脉冲。
没触发就会一直卡在那儿,所以 可以用作同步。如果设置了自动重置,那么wait之后,重置了,那就肯定无法再次进入。

信号量 Semaphore

信号量的和事件比较类似,基本使用步骤: 创建--释放资源--等待--释放资源--关闭
创建:CreateSemaphore
释放资源:ReleaseSemaphore
等待:WaitForSingleObject
关闭:CloseHandle

跨进程,等待函数等待成功后,资源计数会-1。 如果当前资源计数足够,那么还可以等待到。注意: release的时候,释放数量不可超过设定的资源总数
类似事件,没有资源就会卡在那儿。

比较分析

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



你可能感兴趣的:(线程同步与互斥的总结)