2019独角兽企业重金招聘Python工程师标准>>>

秒杀多线程面试题系列

参考JustDoIT —— 大部分内容

《Windows核心编程》线程同步对象速查表

对象 何时处于未触发状态 何时处于触发状态 WaitForSingleObject副作用 内核对象
自动重置事件 ResetEvent,PulseEvent或者等待成功 SetEvent,PulseEvent 重置通知
手动重置事件 ResetEvent,PulseEvent SetEvent,PulseEvent 没有
自动重置可等待计时器 CancelWaitableTimer或等待成功 SetWaitableTimer 重置计时器
手动重置可等待计时器 CancelWaitableTimer SetWaitableTimer 没有
信号量 等待成功时 计数大于0的时候(ReleaseSemaphore) 计数器减1
互斥量 等待成功时 不为线程占用时(ReleaseMutex) 把所有权交给线程
关键段 等待成功时((Try)EnterCriticalSection) 不为线程占用时(LeaveCriticalSection) 把所有权交给线程 ×
SRWLock 等待成功时(AcquireSRWLock(Exclusive)) 不为线程占用时(ReleaseSRWLock(Exclusive) 把所有权交给线程 ×
条件变量 等待成功(SleepConditionVariable*) 被唤醒时(Wake(All)ConditionVariable) 没有 ×

一 同步互斥区别

同步与互斥的区别和联系

互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量

当线程并发执行时,由于资源共享和线程协作,使用线程之间会存在以下两种制约关系。

(1).间接相互制约。一个系统中的多个线程必然要共享某种系统资源,如共享CPU,共享I/O设备,所谓间接相互制约即源于这种资源共享,打印机就是最好的例子,线程A在使用打印机时,其它线程都要等待。

(2).直接相互制约。这种制约主要是因为线程之间的合作,如有线程A将计算结果提供给线程B作进一步处理,那么线程B在线程A将数据送达之前都将处于阻塞状态。

间接相互制约可以称为互斥,直接相互制约可以称为同步,对于互斥可以这样理解,线程A和线程B互斥访问某个资源则它们之间就会产个顺序问题——要么线程A等待线程B操作完毕,要么线程B等待线程操作完毕,这其实就是线程的同步了。因此同步包括互斥,互斥其实是一种特殊的同步。

二 同步互斥的方法

分为两类:用户模式和内核模式。顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。

注:因此,效率上,临界区比互斥量等要高。

用户模式下的方法有:原子操作、临界区、读写锁,条件变量

内核模式下的方法有:互斥量、信号量、事件(手动和自动),可等待计时器(手动和自动)

三 临界区、互斥量、信号量、事件 对比

1、关于线程所有权属性:即某个线程获得该同步工具后,在他释放该工具前可以多次进入想访问的资源,一般来说具有所有权属性的工具不用于线程同步,只用于互斥,具体可以参考本文最前面的几篇博客

2、内核模式下的工具可以用于不同进程的线程之间的同步互斥,用户模式则只能用于相同进程的线程之间

3、只有互斥量在线程异常退出时,会释放对该工具的所有权,其他线程可以继续获取。其他的工具在线程异常退出时,其占有的工具不会释放,其他线程需要一直等待

4、事件分为自动和手动,如果为自动置位,则对该事件调用WaitForSingleObject()后会自动调用ResetEvent()使事件变成未触发状态。

四、死锁

百度百科

是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件。

1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

一个典型的例子是:

线程A锁住了记录1并等待记录2,而线程B锁住了记录2并等待记录1,这样两个线程就发生了死锁现象.

死锁可以用LockCop来检测,其源码地址为https://github.com/lattesir/WindowsViaCPP/tree/master/09-LockCop

注:该工具使用了Windows Vista/ 7提供的WCT API,故需要在Windows Vista/ 7系统运行LockCop检测工具。

windows 多线程编程的几点经验 (防止死锁)

1) 不要在线程函数体内操作MFC控件,不要再线程里面调用UpdateData函数更新用户界面,而应该尽量采用发送消息的方式,在主线程的消息响应函数中操作控件;

注:Winform/WPF中在线程中更新界面会抛出异常,解决办法也是用委托。

2)不建议采用SendMessage往主线程发送消息,因为它是同步的,阻塞的,可以考虑采用PostMessage代替;

3)线程退出时,尽量不要使用TerminateThread函数,而尽可能的让线程自己退出;

注:在线程中有malloc/new等操作,强行终止,1会导致内存泄露,2是因为整个进程在分配和回收内存时,都要用同一把锁,如果TerminateThread之后再new很有可能会死锁。CloseHandle(),TerminateThread(),ExitThread()的区别

4) 当线程退出时,必须先等待工作者线程退出,主线程才退出,但是在主线程里面不要使用WaitForSingleObject或WaitForMultiObjects等待线程结束,因为它可能造成死锁,当主线程使用这两个函数时,主线程就挂起了,尤其在第 (1), (2) 种情况下,工作者线程还在调用主线程里面的资源,这样造成死锁;

5) 为了防止退出死锁的发生,尽量使用MsgWaitForMultipleObjects函数,因为该函数等待时,可以等待线程句柄 有信号,而且还可以等待消息,不会造成死锁;

转载于:https://my.oschina.net/shanlilaideyu/blog/481608

windows多线程同步互斥--总结相关推荐

  1. MFC多线程同步互斥

    MFC多线程同步互斥[转载] http://blog.sina.com.cn/s/blog_62d15fb601017dhn.html https://www.cnblogs.com/zhanghu5 ...

  2. windows多线程同步--临界区

    推荐参考博客:秒杀多线程第五篇 经典线程同步 关键段CS 关于临界区的观念,一般操作系统书上面都有. 适用范围:它只能同步一个进程中的线程,不能跨进程同步.一般用它来做单个进程内的代码快同步,效率比较 ...

  3. Linux多线程同步——互斥锁

    互斥锁 当多个线程对同一个资源进行访问的时候,为了这个资源的安全性,我们需要对这个资源进行锁定,规定同一时间只有一个资源能够获得该锁的钥匙,其它线程要获得该资源需要等待该线程 互斥锁创建 pthrea ...

  4. 秒杀多线程第十二篇 多线程同步内功心法——PV操作上

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  5. 多线程面试题系列(12):多线程同步内功心法——PV操作上

    上面的文章讲解了在Windows系统下实现多线程同步互斥的方法,为了提高在实际问题中分析和思考多个线程之间同步互斥问题的能力,接下来将讲解PV操作,这也是操作系统中的重点和难点.本文将会先简要介绍下P ...

  6. [一个经典的多线程同步问题]解决方案一:关键段CS

    前面提出了一个经典的多线程同步互斥问题,本篇将用关键段CRITICAL_SECTION来尝试解决这个问题. 本文先介绍如何使用关键段,然后再深层次的分析下关键段的实现机制和原理. 关键段CRITICA ...

  7. C++实现多线程及其三种方法实现多线程同步

    1.调用windows API实现多线程 #include "stdafx.h" #include <windows.h> #include <stdio.h&g ...

  8. 【转】windows平台多线程同步之Mutex的应用

    线程组成: 线程的内核对象,操作系统用来管理该线程的数据结构. 线程堆栈,它用于维护线程在执行代码时需要的所有参数和局部变量.   操作系统为每一个运行线程安排一定的CPU时间 -- 时间片.系统通过 ...

  9. 秒杀多线程第七篇 经典线程同步 互斥量Mutex

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

最新文章

  1. c++ lambda函数_C++ Lambda表达式
  2. 关于建立完整商业应用软件框架库的设想
  3. Ubuntu tensorflow自定义GPU版本op节点
  4. fastjson解析多层数据_JSON数据如何进行解析呢,方式有哪些?
  5. cocoapods 详尽使用
  6. 跨站点脚本编制-XSS 描述及解决方法
  7. 圆上的定理 —— 圆周角定理与相交弦定理
  8. miui v5 android版本,miuiv5主题下载-miuiv5主题(MiroEX) 安卓版v3.4.1-PC6安卓网
  9. VS2010 安装OpenCV2.4.0教程
  10. 时间序列预测的机器学习方法
  11. 比特大陆60天 :夺权、立威下的疯狂裁员
  12. RTL设计基础(一)
  13. 汽车修理厂计算机管理,最新汽车维修厂管理系统
  14. 不朽的浪漫网站服务器,浪漫人族TOD专访 虫族强大让我震惊
  15. 钆螯合层析结合对比剂/DPPE-DTPA-Gd-DPPE造影剂/DMPE-DTPA-Gd-DMPE造影剂
  16. S3C6410 硬件加速功能
  17. 高仿网易云音乐一(可扫描本地音乐播放)
  18. IE浏览器确定兼容性模式
  19. 物联网无线通讯wifi模块AP和STA模式分别是什么意思?
  20. PDF文件内部结构分析查看器-java

热门文章

  1. 在百度超级链Xuper上部署智能合约并实现存证功能
  2. jpa 跨表_JPA的多表复杂查询
  3. onvif开发之设备发现功能的实现
  4. 关于Zipkin的几个问题
  5. Sentinel配置规则持久化
  6. 微软是如何使用C#重写C#编译器并将其开源的
  7. AsyncDisplayKit官方文档个人翻译
  8. koajs 项目实战(二)
  9. MongoDB(五)-- 副本集(replica Set)
  10. 使用performance monitor 查看 每一个cpu core的cpu time