2013-08-10 15:45:31算法
这两天看进程的同步与通讯,看了几本书上的介绍,也从网上搜了不少资料,越看越迷惑,被这几个问题搞得很纠结。数据库
在好多教材上(包括国内与国外的)也没有明确这些概念,如今对每一个问题尚未准确的答案,下面将本身的理解记下来,之后再补充。编程
参考资料:安全
《操做系统教程》 孙钟秀主编 费翔林 骆斌 谢立参编 高等教育出版社网络
《计算机操做系统》 何炎祥 李飞 李宁 编著 清华大学出版社(进程管理部分与《操做系统教程》中的相似)多线程
进程互斥、同步的概念是并发进程下存在的概念,有了并发进程,就产生了资源的竞争与协做,从而就要经过进程的互斥、同步、通讯来解决资源的竞争与协做问题。并发
下面是根据《操做系统教程》3.1.4 中的介绍,整理的进程互斥、同步的概念。socket
在多道程序设计系统中,同一时刻可能有许多进程,这些进程之间存在两种基本关系:竞争关系和协做关系。分布式
进程的互斥、同步、通讯都是基于这两种基本关系而存在的,为了解决进程间竞争关系(间接制约关系)而引入进程互斥;为了解决进程间松散的协做关系( 直接制约关系)而引入进程同步;为了解决进程间紧密的协做关系而引入进程通讯。模块化
第一种是竞争关系
系统中的多个进程之间彼此无关,它们并不知道其余进程的存在,而且也不受其余进程执行的影响。例如,批处理系统中创建的多个用户进程, 分时系统中创建的多个终端进程。因为这些进程共用了一套计算机系统资源,于是, 必然要出现多个进程竞争资源的问题。当多个进程竞争共享硬设备、存储器、处理器 和文件等资源时,操做系统必须协调好进程对资源的争用。
资源竞争出现了两个控制问题:一个是死锁 (deadlock )问题,一组进程若是都得到了部分资源,还想要获得其余进程所占有的资源,最终全部的进程将陷入死锁。另外一个是饥饿(starvation )问题,这是指这样一种状况:一个进程因为其余进程老是优先于它而被无限期拖延。
操做系统须要保证诸进程能互斥地访问临界资源,既要解决饥饿问题,又要解决死锁问题。
进程的互斥(mutual exclusion )是解决进程间竞争关系( 间接制约关系) 的手段。 进程互斥指若干个进程要使用同一共享资源时,任什么时候刻最多容许一个进程去使用,其余要使用该资源的进程必须等待,直到占有资源的进程释放该资源。
第二种是协做关系
某些进程为完成同一任务须要分工协做,因为合做的每个进程都是独立地以不可预知的速度推动,这就须要相互协做的进程在某些协调点上协 调各自的工做。当合做进程中的一个到达协调点后,在还没有获得其伙伴进程发来的消息或信号以前应阻塞本身,直到其余合做进程发来协调信号或消息后方被唤醒并继续执行。这种协做进程之间相互等待对方消息或信号的协调关系称为进程同步。
进程间的协做能够是双方不知道对方名字的间接协做,例如,经过共享访问一个缓冲区进行松散式协做;也能够是双方知道对方名字,直接经过通讯机制进行紧密协做。容许进程协同工做有利于共享信息、有利于加快计算速度、有利于实现模块化程序设计。
进程的同步(Synchronization)是解决进程间协做关系( 直接制约关系) 的手段。进程同步指两个以上进程基于某个条件来协调它们的活动。一个进程的执行依赖于另外一
个协做进程的消息或信号,当一个进程没有获得来自于另外一个进程的消息或信号时则需等待,直到消息或信号到达才被唤醒。
不难看出,进程互斥关系是一种特殊的进程同步关系,即逐次使用互斥共享资源,也是对进程使用资源次序上的一种协调。
下面是根据《操做系统教程》3.5 中的介绍,整理的进程通讯的概念。
并发进程之间的交互必须知足两个基本要求:同步和通讯。
进程竞争资源时要实施互斥,互斥是一种特殊的同步,实质上须要解决好进程同步问题,进程同步是一种进程通讯,经过修改信号量,进程之间可创建起联系,相互协调运行和协同工做。可是信号量与PV操做只能传递信号,没有传递数据的能力。有些状况下进程之间交换的信息量虽不多,例如,仅仅交换某个状态信息,但不少状况下进程之间须要交换大批数据,例如,传送一批信息或整个文件,这能够经过一种新的通讯机制来完成,进程之间互相交换信息的工做称之为进程通讯IPC (InterProcess Communication)(主要是指大量数据的交换)。进程间通讯的方式不少,包括:
前面提到,进程互斥关系是一种特殊的进程同步关系,下面给出常见的进程同步的方法,实际上也可用于进程的互斥(我的理解)。
在何炎祥的《计算机操做系统》 3.2 节,将进程同步的机制与解决进程互斥方法看作是同样的,的明确指出互斥的软件解决方法为Dekker算法与Peterson算法,互斥的硬件解决方法为中断方法、以及使用机器指令的方法,后面又给出了信号量、管程、消息传递三种方法。
实际应用中,不一样的系统有不一样的进程同步方法,CSDN帖子http://bbs.csdn.net/topics/80156687中有一些讨论,Linux 与Windows的主要同步、通讯机制以下:
Linux 下:
Linux 下常见的进程同步方法有:SysVIPC 的 sem(信号量)、file locking / record locking(经过 fcntl 设定的文件锁、记录锁)、futex(基于共享内存的快速用户态互斥锁)。针对线程(pthread)的还有 pthread_mutex 和 pthread_cond(条件变量)。
Linux 下常见的进程通讯的方法有 :pipe(管道),FIFO(命名管道),socket(套接字),SysVIPC 的 shm(共享内存)、msg queue(消息队列),mmap(文件映射)。之前还有 STREAM,不过如今比较少见了(好像)。
Windows下:
在Windwos中,进程同步主要有如下几种:互斥量、信号量、事件、可等计时器等几种技术。
在Windows下,进程通讯主要有如下几种:内存映射、管道、消息等,可是内存映射是最基础的,由于,其余的进程通讯手段在内部都是考内存映射来完成的。
对于该问题,教材上没有明确的回答,教材上给出的通常是进程而非线程的同步、通讯方式。但网络上不少说法将二者混为一谈。根据教材,以及网上的说法,我的的理解为:
同步机制:
信号量、管程、互斥是进程的同步机制,而信号量、互斥也可用于线程的同步,但管程只在进程同步中被用到;
线程的同步除了信号量、互斥外,还有临界区、事件,没有看到教材上将这两种方式做为进程的同步方式;
通讯机制:
管道、FIFO、消息队列、信号量、共享内存是进程的同步机制,教材上没有线程的通讯机制这样的说法,但能够确定这几种方法是进程的通讯方式,且其中的信号量既可用于进程的同步,又可用于进程的通讯,在网络上还有说能够用于线程同步的。
管道与管程是不一样的,管程是进程同步的方式,而管道则是进程通讯的方式。
下面是常见的线程之间的同步方式的详细介绍。
(注:下面转自网络,下面的同步、通讯方式对于进程与线程分的不是很清楚,关于进程仍是线程的解释见上面——线程的同步/通讯与进程的同步/通讯有区别吗?)
1、进程/线程间同步机制。
临界区、互斥区、事件、信号量四种方式
临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)的区别
一、临界区:经过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
在任意时刻只容许一个线程对共享资源进行访问,若是有多个线程试图访问公共资源,那么在有一个线程进入后,其余试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其余线程才能够抢占。
二、互斥量:采用互斥对象机制。
只有拥有互斥对象的线程才有访问公共资源的权限,由于互斥对象只有一个,因此能保证公共资源不会同时被多个线程访问。互斥不只能实现同一应用程序的公共资源安全共享,还能实现不一样应用程序的公共资源安全共享 .互斥量比临界区复杂。由于使用互斥不只仅可以在同一应用程序不一样线程中实现资源的安全共享,并且能够在不一样应用程序的线程之间实现对资源的安全共享。
三、信号量:它容许多个线程在同一时刻访问同一资源,可是须要限制在同一时刻访问此资源的最大线程数目 .
信号量对象对线程的同步方式与前面几种方法不一样,信号容许多个线程同时使用共享资源,这与操做系统中的PV操做相同。它指出了同时访问共享资源的线程最大数目。它容许多个线程在同一时刻访问同一资源,可是须要限制在同一时刻访问此资源的最大线程数目。
PV操做及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。信号量S是一个整数,S大于等于零时表明可供并发进程使用的资源实体数,但S小于零时则表示正在等待使用共享资源的进程数。
P操做申请资源:
(1)S减1;
(2)若S减1后仍大于等于零,则进程继续执行;
(3)若S减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,而后转入进程调度。
V操做 释放资源:
(1)S加1;
(2)若相加结果大于零,则进程继续执行;
(3)若相加结果小于等于零,则从该信号的等待队列中唤醒一个等待进程,而后再返回原进程继续执行或转入进程调度。
四、事 件: 经过通知操做的方式来保持线程的同步,还能够方便实现对多个线程的优先级比较的操做 .
总结:
1. 互斥量与临界区的做用很是类似,但互斥量是能够命名的,也就是说它能够跨越进程使用。因此建立互斥量须要的资源更多,因此若是只为了在进程内部是用的话使用临界区会带来速度上的优点并可以减小资源占用量。由于互斥量是跨进程的互斥量一旦被建立,就能够经过名字打开它。
2. 互斥量(Mutex),信号灯(Semaphore),事件(Event)均可以被跨越进程使用来进行同步数据操做,而其余的对象与数据同步操做无关,但对于进程和线程来说,若是进程和线程在运行状态则为无信号状态,在退出后为有信号状态。因此可使用WaitForSingleObject来等待进程和线程退出。
3. 经过互斥量能够指定资源被独占的方式使用,但若是有下面一种状况经过互斥量就没法处理,好比如今一位用户购买了一份三个并发访问许可的数据库系统,能够根据用户购买的访问许可数量来决定有多少个线程/进程能同时进行数据库操做,这时候若是利用互斥量就没有办法完成这个要求,信号灯对象能够说是一种资源计数器。
2、进程间通讯方式
因为比较容易混淆,咱们把进程间通讯方法也列在这里作比较。
进程通讯也就是所谓的IPC问题,主要是指进程间交换数据的方式。进程通讯包括高级通讯与低级通讯,其中进程同步与互斥属于低级通讯,主要用于插U农地控制信号;高级通讯包括三种:共享存储系统(有的地方称做共享内存区)、消息传递系统(有的地方称做消息队列)、管道。
信号量是进程同步与互斥的经常使用方法,也能够做为低级的进程通讯方法,用于传递控制信号。
简而言之,进程间通讯方式主要包括管道、FIFO、消息队列、信号量、共享内存。
1.管道,还有命名管道和非命名管道(即匿名管道)之分,非命名管道(即匿名管道)只能用于父子进程通信,命名管道可用于非父子进程,命名管道就是FIFO,管道是先进先出的通信方式
2.消息队列,是用于两个进程之间的通信,首先在一个进程中建立一个消息队列,而后再往消息队列中写数据,而另外一个进程则从那个消息队列中取数据。须要注意的是,消息队列是用建立文件的方式创建的,若是一个进程向某个消息队列中写入了数据以后,另外一个进程并无取出数据,即便向消息队列中写数据的进程已经结束,保存在消息队列中的数据并无消失,也就是说下次再从这个消息队列读数据的时候,就是上次的数据!!!!
3.信号量,它与WINDOWS下的信号量是同样的,因此就不用多说了
4.共享内存,相似于WINDOWS下的DLL中的共享变量,但LINUX下的共享内存区不须要像DLL这样的东西,只要首先建立一个共享内存区,其它进程按照必定的步骤就能访问到这个共享内存区中的数据,固然可读可写
以上几种方式的比较:
1.管道:速度慢,容量有限,只有父子进程能通信
2.FIFO:任何进程间都能通信,但速度慢
3.消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题
4.信号量:不能传递复杂消息,只能用来同步
5.共享内存区:可以很容易控制容量,速度快,但要保持同步,好比一个进程在写的时候,另外一个进程要注意读写的问题,至关于线程中的线程安全,固然,共享内存区一样能够用做线程间通信,不过没这个必要,线程间原本就已经共享了同一进程内的一块内存
本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取情况。通常说来,为了得到共享资源,进程须要执行下列操做:
3、进程/线程同步机制与进程间通讯机制比较
很明显2者有相似,可是差异很大
同步主要是临界区、互斥、信号量、事件
进程间通讯是管道、内存共享、消息队列、信号量、socket
共通之处是,信号量和消息(事件)
信号量是进程同步与互斥的经常使用方法,也能够做为低级的进程通讯方法,用于传递控制信号;
管道与管程是不一样的,管程是进程同步的方式,而管道则是进程通讯的方式;