多核时代:并行程序设计探讨(5)——Windows和Linux对决(进程间同步)-阿里云开发者社区

开发者社区> 华仔爱技术> 正文

多核时代:并行程序设计探讨(5)——Windows和Linux对决(进程间同步)

简介:
+关注继续查看

Windows和Linux对决(线程间同步)

1.1        Windows线程同步

1.1.1   关键代码区Critical Section

所谓“关键代码区”,相信大家看名字也能理解个大概了。首先:它很关键,第二:它是代码区。之所以关键,当然目的就是每次只能一个线程能够进入;既然是代码区,那就是只能在一组拥有同样代码的线程中用。

那什么情况下会用到关键代码区呢?当然是要保护多个线程都会用到的东西了,说到这里,想必你已经猜到了:全局变量和静态变量

1.1.2   互斥Mutex

互斥看起来和关键代码区是一样的,都是每次都是只允许一个线程使用。但互斥和关键代码区相比,具有如下特点:

对比点

关键代码区

互斥

备注

名字

无名字

有名字

NA

跨进程

不能跨进程

可以跨进程

因为有名字,所以可以跨进程

访问模式

没有超时

可以超时

NA

死锁问题

线程挂了其它线程就只能傻等了

线程挂了,操作系统会通知其它线程

NA

运行环境

用户区

内核区

所以关键代码区性能要高一些。

 

1.1.3   信号量Semaphore

信号量本质上就是一个计数器,当计数器大于0时就意味着被保护的对象可用。每次申请计数器就减1,释放就加1.

信号量和互斥体相比,一个最明显的差别就在于互斥体每次只能有一个线程进行访问,而信号量可以有多个线程进行访问。

看到这里,大家可能都像我开始一样存在这样的问题:如果将信号量最大值设置为1,那么不就是相当于互斥量了吗

看起来是一样的,而且在有些系统上也确实是这样的,据说是互斥体底层就是信号量来实现的,或者干脆就没有互斥体(例如传统UNIX),但在有的系统上还是有差别的,差别在于:申请和释放是否要同一个线程完成Windows就是这种形式。互斥体要求同一线程来申请和释放,而信号量就可以由不同的线程申请和释放(但是我很难想象这样做有什么好处,难倒要给一个线程集中获取信号量,再来通知另外的线程工作?)。

1.1.4   事件Event

事件本质上是一个系统信号,即:发生了某件事情后,发一个信号给其它关心这件事情的线程。

从事件的本质上来看,事件不是为了资源保护的,而是为了线程间通知用的。举个简单的例子:Socket接收完一个消息后,将其放入队列,然后需要通知消息处理线程进行处理。

大家想想,如果没有事件通知会怎么样呢?那接收线程只能设一个定时器或者循环,定时甚至循环去查询队列中是否有消息,这种定时和循环处理是对系统性能的极大浪费,所以,有了事件后,就不用这么浪费了。

 

1.2        Linux线程同步

介绍完WindowsLinux介绍就很方便了,就像上一篇博文提到的一样,WindowsLinux其实很多地方相似,线程同步也不例外。

1.2.1   关键代码区???

不好意思,Linux没有这个东东

1.2.2   互斥Mutex

LinuxWindows是一样的,这里就不详细介绍了,需要注意的是传统UNIX并没有互斥这个东东,传统UNIX的互斥是通过二元信号量(即最大值为1)来实现的。

1.2.3   信号量Semaphore

需要注意的是Linux中信号量有两种:一种是内核POSIX标准的信号量,一种是用户态的传统UNIX IPC信号量。两者的差别如下:

对比点

POSIX Semaphore

IPC Semaphore

备注

控制者

内核

用户

IPC Semaphore可以通过semctrl函数修改对外表现。

权限控制

不允许修改

用户可修改

NA

性能

优于IPC

劣于POSIX

NA

范围

进程级

系统级

如果进程退出时忘记关闭,POSIX会自动释放。

POSIX信号量和Windows的信号量是一样的。

1.2.4   条件变量Conditions

看到这个名字有点莫名其妙,条件变量和线程同步有什么关系呢?

但其实是Linux(或者是POSIX)的名字取得不好才导致我们很难理解,本质上条件变量就是Windows的事件,作用也是一样的。唉,如果Linux或者POSIX不想和Windows同名,改成叫“通知”也能让我们这些小虾多省点脑力啊:)

1.2.5   信号Signal

类似于“共享内存”也是一种进程间通信的方式一样,我把信号也列进来作为线程同步的一种,因为本质上信号不是为了线程间同步而设计的,但我们可以利用其作为线程同步来使用。

如何使用信号呢?既然信号本身就是一种通知(还记得上面我建议将“条件变量”建议改名为什么吗?),那我们就按照通知来使用了,例如:A做完了某事,发一个信号给BB收到后开始启动做另外一件事。

请注意:和“条件变量”不同的是,条件变量支持广播机制,而信号只能是点对点,因此实际使用中应该还是“条件变量”方便一些。当然如果是传统UNIX,那就只能利用信号来进行通知了。

===============================================================================

 

 

注:看我的博客的朋友可能会发现一个现象,我几乎从来不介绍详细的函数或者API,而基本上都在“归纳、总结、对比”。这是我个人的一个风格或者理解吧,我认为函数或者API用的时候查一下就可以了,而在分析和设计的时候,关键是要知道有哪些东西可以给我们用,而且要知道我们具体究竟应该用哪个,因此在平时就必须多归纳、总结、对比,而不是背住各种函数和API。

==========================未完待续===============================

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
《OpenACC并行程序设计:性能优化实践指南》一 3.11 小结
本节书摘来自华章出版社《OpenACC并行程序设计:性能优化实践指南》一 书中的第3章,第3.11节,作者:[美] 罗布·法伯(Rob Farber),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
909 0
《OpenACC并行程序设计:性能优化实践指南》一 3.12 参考文献
本节书摘来自华章出版社《OpenACC并行程序设计:性能优化实践指南》一 书中的第3章,第3.12节,作者:[美] 罗布·法伯(Rob Farber),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
592 0
《UNIX网络编程 卷2:进程间通信(第2版)》——1.9 小结
各种类型IPC的持续性可以是随进程持续的、随内核持续的或随文件系统持续的,这取决于IPC对象存在时间的长短。在为给定的应用选择所用的IPC类型时,我们必须清楚相应IPC对象的持续性。
1222 0
+关注
华仔爱技术
热爱技术的10多年IT老兵,既能深入底层写代码,又能高屋建瓴做架构;可以带领团队往前冲,也能侃侃而谈做演讲。著有《面向对象葵花宝典:思想、技巧与实践》。
114
文章
1
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载