0%

Process/Thread Synchronization

进程间同步

进程同步是为了控制多个进程的执行顺序,为了做到进程同步,通常需要进程间通信(IPC),在不同进程之间传递消息,常见的方式有以下几种:

  • 管道(pipe):包括匿名管道、流管道和命名管道(FIFO)。速度慢效率低,容量有限,只能用于父子进程
  • 信号量(semaphores):不能用来传递复杂消息,只能用于同步
  • 共享内存(shared memory):高级方式
  • 消息队列(message passing):容量有限,消息的复制耗时,不适于信息量大或操作频繁的场景
  • 信号(signal):
  • 套接字(socket):网络上不同进程通信

管道

对于匿名管道:

  1. 半双工即数据只能单向流动,有固定的读端和写端
  2. 只能在父子进程或兄弟进程间通信
  3. 可以看作特殊文件并使用read/write读写,只存在于内存中,不属于任何文件系统

对于命名管道:

  1. 可以在无关进程间交换数据
  2. 拥有相关联的路径名,以一种特殊设备文件形式存在于文件系统

消息队列

消息队列是存放在内核中的消息链表,由队列ID来标识:

  1. 消息有特定格式和特定优先级
  2. 独立于发送和接收进程,进程终止消息队列仍然存在
  3. 可以根据消息类型有选择地接收信息

信号量

本质上是一个计数器,用来进程间互斥和同步,而非用于存储进程间通信数据。PV原语操作

信号

异步通信方式

共享内存

速度最快,直接对内存存取,需要同步机制,通常与信号量结合使用

socket

不同主机间IPC

线程间同步/通信

线程同步机制有以下几种:

锁机制

  • 互斥锁(mutex):排他性访问共享数据,用来保护临界区。某个线程加锁后,其它要加锁的线程将被阻塞,申请失败进入休眠,直到锁被释放。
  • 读写锁(ReadWriteLock):用于读者-写者问题,共有三种状态:不加锁、读模式加锁、写模式加锁。每次只有一个线程可以占用写模式的锁,但可以有多个线程占有读模式锁。
  • 自旋锁(spinlock):专为多处理器并发引入,不断循环测试锁的状态,申请线程不会休眠,忙等锁。
  • 条件变量(condition variables)

全局变量

在各线程共享的堆上,每个线程私有栈

事件event

信号量

  • 信号量(semaphores):有更多取值空间,实现更复杂的同步。

信号量和PV原语的使用可归纳为三种情形:

  1. 把信号量视为加锁标志位,其目的是为了实现对某个唯一的共享数据互斥访问,如各个进程间的某共享变量,数据库中的某个记录。
    共享数据的值与信号量本身的值没有直接关系,信号量的作用仅仅是作为加锁标志位。其特征是信号量初始值为1,然后在一个进程内部对它进行配对的PV操作。
    1
    2
    3
    4
    P(mutex);  // mutex的初始值为1
    访问该共享数据;
    V(mutex);
    非临界区
  2. 把信号量视为某种类型的共享资源的剩余个数,目的是实现对这种类型的共享资源的访问,如各种I/O设备。
    信号量的取值具有实际意义,即为空闲资源的个数。多个进程可以同时使用这种类型的资源,直到所有空闲资源均已用完。
    其特征是信号量的初始值为\(N\geq 1\),然后在一个进程内部对它进行配对的PV操作
    1
    2
    3
    4
    P(resource);  // resource的初始值为N
    使用该资源;
    V(resource);
    非临界区
  3. 把信号量作为进程间同步的工具,利用它来设定两个进程在运行时的先后顺序。比如,它可以是某个共享资源的当前个数,但是由一个进程负责生成该资源,而另一个进程负责消费该资源,由此引发了两个进程间的先后顺序。
    其特征是信号量的初始值为\(N\geq 0\),然后在一个进程里对其使用V原语,增加资源个数,而在另一个进程里对其使用P原语,减少资源个数,从而实现两个进程之间的同步关系。

reference

IPC介绍
进程间通信
信号与信号量
线程间同步
https://www.cnblogs.com/meng-chao/p/16323985.html
https://www.cnblogs.com/limich/p/7477079.html