多核时代:并行程序设计探讨(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线程同步

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

1.2.1   关键代码区???

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

1.2.2   互斥Mutex

Linux和Windows是一样的,这里就不详细介绍了,需要注意的是传统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做完了某事,发一个信号给B,B收到后开始启动做另外一件事。

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

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

 

 

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

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

时间: 2024-11-08 18:55:04

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

多核时代:并行程序设计探讨(3)——Windows和Linux对决(多进程多线程)

并行程序设计探讨(3)--Windows和Linux对决(多进程多线程) 前面的博文经过分析总结,最后得出两种并行技术:多进程多线程.多机协作.对于多进程和多线程来说,最有代表性且最常见的的莫过于Windows和Linux(作为UNIX类操作系统的代表,下同)这两个操作系统了. 真是冤家路窄,Windows和Linux这对冤家在这里又碰面了!! 当然,我这里不是要挑起Windows和Linux谁优谁劣的争论,对于一个真正的技术人来说,Windows和Linux本身并没有优劣之分,只有在不同的使用

多核时代:并行程序设计探讨(2)——并行实现技术

并行程序设计探讨(2)--并行实现技术 通过"并行程序设计探讨(1)"的介绍,相信大家都已经对并行系统相关的概念有了初步的了解.不过看起来挺吓人的,一堆的术语和概念,想起来头就有点大!! 幸运的是真正需要进行并行程序设计的系统其实不多,我们来看看: SISD:本质上决定了不可能是并行的: SIMD:专有系统,相信绝大部分人都没有接触过: MISD:没有这样的系统: MIMD:本质上就是为了支持并行的. 因此,在处理并行程序设计的时候,我们其实只要考虑MIMD这类系统就OK了!谢天谢地O

多核时代:并行程序设计探讨(1)——并行系统

  并行程序设计探讨(1)--并行系统 大家可能会有疑问:你一会儿并行,一会儿多核,到底是谁跟谁啊? 我开始也有这个疑问,甚至以为并行就是多核,其实两个并不能对等,一句话就是:多核是并行的一种. 并行本身是一个广泛的概念,其实早在多核之前并行处理就已经存在N久了,大家想想看:IBM.SUN.HP的小型机,哪个不是多CPU的?甚至连DELL的工作站,都是两CPU的,更不用说那些中型机.大型机.巨型机了.所以说"并行处理"是一个比"多核处理"要广泛.要早的多的技术,多核

多核时代:并行程序设计探讨(7)——并行编程模式概览

                                          并行编程模式概览 前面的5.6篇博文,都是和并行编程相关的基础知识,如果你一路看来,基本上也能够开始进行并行编程设计了,也可以和别人吹吹牛.聊聊天了. 但"欲穷千里目,更上一层楼",前面的毕竟都是基础知识,拿来直接设计,虽然能够完成任务,但就像在茫茫大海中航行,没有灯塔,难免会走很多弯路.甚至绝路! 所以我们要在这些基础知识之上,学习一套系统的分析问题.设计方案.应用实现的理论来指导我们作出正确的.优秀

《多核与GPU编程:工具、方法及实践》----第2章 多核和并行程序设计 2.1 引言

第2章 多核和并行程序设计 本章目标 学习设计并行程序的PCAM方法. 使用任务图和数据依赖图来识别可以并行执行的计算部分. 学习将问题的解法分解为可并发执行部分的流行的分解模式. 学习编写并行软件的主要程序结构模式,如主/从和fork/join. 理解分解模式的性能特点,如流水线. 学习如何结合分解模式和合适的程序结构模式. 2.1 引言 即使是对于经验丰富的专业程序员,向多核编程的过渡也并不简单.多核和并行编程往往会打破语句按严格顺序执行的串行程序的传统风格.当许多事情在同一时间发生时,正如

多核时代:并行程序设计探讨(4)——Windows和Linux对决(进程间通信)

                             进程间通信 多进程和多线程本质上就是将原来一个进程或者线程处理的任务分给了多个进程或者线程,也可以说是将原来一个CPU处理的任务分给了多个CPU处理,类似于随着生产力的发展,原来一个人包打天下的个人英雄主义时代被分工合作的团队取代一样. 既然是一个团队,就必然涉及到分工合作问题,并行程序的设计本质上就是解决"分工"和"合作"的问题.其中"分工"主要是后面讲到"并行程序设计模式&q

多核时代:并行程序设计探讨(6)——多机协作(又叫分布式处理)

                                  多机协作(又叫分布式处理) 嗯,费了九牛二虎之力,终于将Windows和Linux对比完了.你是否准备伸个懒腰,喝杯热咖啡,听点音乐来放松一下呢? 别急,革命尚未成功,同志还需努力,铁还得趁热打.还记得第二篇博文里面总结的两种并行实现技术没有?一个是"多进程多线程",另一个是"多机协作",到目前为止我们基本上只把"多进程多线程"分析完毕了,还有另外一个"多机协作&quo

多核时代:并行程序设计探讨(9)——数据分解模式Data Decomposition

                                                   Data Decomposition 1.1        问题 如何将待解决的问题的数据分解为能够并行运行的数据单元(units)? 1.2        上下文 并行算法的设计者必须首先详细了解待解决的问题,除此之外,还必须识别如下几个关键因素: 1)计算强相关的部分:待解决问题中的哪部分需要进行大量运算: 2)关键数据结构:主要是对什么数据进行运算:如何进行运算.   当基本问题理解后,设

多核时代:并行程序设计探讨(8)——任务分解模式Task Decomposition

                                                              Task Decomposition 从本章开始我们就正式来介绍每个模式了,参考设计模式的做法,每个模式我们都按照如下的内容进行介绍:问题(Problem).上下文(context).考虑因素(Forces).解决方法(Solutions).至于样例,就请各位看官直接看原文了.   1.1        问题 如何将待解决的问题分解为能够并行运行的"任务(task)&quo