最近也是遇到很多进程、线程同步、互斥,进程间通信的问题,这些问题放在一起很容易引起混淆,最近也查阅了相关的书籍资料和一些博客,在此写出自己的一些相关总结,希望对大家有帮助。
首先要说的是进程、线程两种最基本的关系:竞争关系和协作关系
进程的互斥、同步、通信都是基于这两种基本关系而存在的:
1.为了解决进程间竞争关系(间接制约关系)而引入进程互斥;
2.为了解决进程间松散的协作关系( 直接制约关系)而引入进程同步;
3.为了解决进程间紧密的协作关系而引入进程通信
定义(以进程为例):
进程互斥:指若干个进程要使用同一共享资源时,任何时刻最多允许一个进程去使用,其他要使用该资源的进程必须等待,直到占有资源的进程释放该资源。
进程的同步:是解决进程间协作关系( 直接制约关系) 的手段。进程同步指两个以上进程基于某个条件来协调它们的活动。一个进程的执行依赖于另一个协作进程的消息或信号,当一个进程没有得到来自于另一个进程的消息或信号时则需等待,直到消息或信号到达才被唤醒
进程通信:进程之间互相交换信息的工作称之为进程通信IPC (InterProcess Communication),多个进程之间相互通信,交换信息传递数据的方法
接下来分别说一下各部分:
进程同步:
不同的操作系统下进程同步的方式不同:
Linux 下:
Linux 下常见的进程同步方法有:SysVIPC 的 sem(信号量)、file locking / record locking(通过 fcntl 设定的文件锁、记录锁)、futex(基于共享内存的快速用户态互斥锁)。针对线程(pthread)的还有 pthread_mutex 和 pthread_cond(条件变量)。
Windows下:
在Windwos中,进程同步主要有以下几种:互斥量、信号量、事件、可等计时器等几种技术。
在Windows下,进程通信主要有以下几种:内存映射、管道、消息等,但是内存映射是最基础的,因为,其他的进程通信手段在内部都是考内存映射来完成的
以上所说的是进程的同步方式,接下来介绍线程常见的同步方式,这也是进程常见的同步方式:
线程间的同步方式:常见的同步机制主要是:临界区、互斥区、事件、信号量这四种
临界区:
临界区对应着一个CcriticalSection对象,当线程需要访问保护数据时,调用EnterCriticalSection函数;当对保护数据的操作完成之后,调用LeaveCriticalSection函数释放对临界区对象的拥有权,以使另一个线程可以夺取临界区对象并访问受保护的数据。
PS:关键段对象会记录拥有该对象的线程句柄即其具有“线程所有权”概念,即进入代码段的线程在leave之前,可以重复进入关键代码区域。所以关键段可以用于线程间的互斥,但不可以用于同步(同步需要在一个线程进入,在另一个线程leave)
互斥量:
互斥与临界区很相似,但是使用时相对复杂一些(互斥量为内核对象),不仅可以在同一应用程序的线程间实现同步,还可以在不同的进程间实现同步,从而实现资源的安全共享。
信号量:
信号量的用法和互斥的用法很相似,不同的是它可以同一时刻允许多个线程访问同一个资源,PV操作
事件:
事件分为手动置位事件和自动置位事件。事件Event内部它包含一个使用计数(所有内核对象都有),一个布尔值表示是手动置位事件还是自动置位事件,另一个布尔值用来表示事件有无触发。由SetEvent()来触发,由ResetEvent()来设成未触发。
注:信号量是进程同步与互斥的常用方法,也可以作为低级的进程通信方法
接下来说一下进程间的通信方式:
进程同信:
根据进程通信时信息量大小的不同,可以将进程通信划分为两大类型:
1、低级通信,控制信息的通信(主要用于进程之间的同步,互斥,终止和挂起等等控制信息的传递)
2、高级通信,大批数据信息的通信(主要用于进程间数据块数据的交换和共享,常见的高级通信有管道,消息队列,共享内存等).
进程通信的具体方式:
1.管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,提供的共享文件通信机制
2.有名管道 (named pipe) : 有名管道也是半双工的通信方式
3.信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。不是用于交换大批数据,而用于多线程之间的同 步.常作为一种锁机制,防止某进程在访问资源时其它进程也访问该资源。
4.消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。
5.信号 ( signal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
6.共享内存( shared memory ):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。
7.套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
注:管道与管程是不同的,管程是进程同步的方式,而管道则是进程通信的方式
这里再简单介绍一下线程通信的三种方式:
线程间通信:
1.使用全局变量
主要由于多个线程可能更改全局变量,因此全局变量最好声明为violate
2.使用消息实现通信
在Windows程序设计中,每一个线程都可以拥有自己的消息队列(UI线程默认自带消息队列和消息循环,工作线程需要手动实现消息循环),因此可以采用消息进行线程间通信
3.使用事件CEvent类实现线程间通信
Event对象有两种状态:有信号和无信号,线程可以监视处于有信号状态的事件,以便在适当的时候执行对事件的操作。
综上所述:进程互斥、同步与通信的关系:互斥是一种特殊的同步,进程同步是一种进程通信,由此看来,进程互斥、同步都可以看做进程的通信
希望大家有什么自己的看法可以留言一起进行讨论,谢谢