进程同步是个操作系统级别的概念,进程是占有资源的最小单位(线程可以访问其所在进程内的所有资源,但线程本身并不占有资源),但对于某些资源来说,其在同一时间只能被一个进程占用,这些一次只能被一个进程所占用的资源就是所谓的“临界资源”。例如物理上的打印机,或是在硬盘或者内存中被多个进程共享的一些变量和数据。
现在操作系统中,线程是调度的基本单位,虽然同一个进程的多个线程共享进程的资源,但是不同线程所访问的资源仍然可能存在冲突,因此也同样需要同步和互斥。因此线程间同步与互斥的概念同样适用于进程间通信,但是可能实现的手段不太一样。
同步和互斥的概念
1. 线程同步
- 线程同步也是线程之间的约束关系,是为了完成某种任务而建立的两个或者多个线程,这个线程需要在某些位置上协调他们的工作次序而等候、传递信息所产生的制约关系。线程间的制约关系源于他们的合作。
比如说线程B需要从缓冲区中读取线程A产生的数据,当缓冲区为空时,线程B因为读不到数据而被阻塞。当线程A产生信息放入缓冲区时,线程B才会被唤醒。如图所示:
2.线程互斥
- 线程互斥是线程之间的间接约束关系。当一个线程进入临界区使用临界资源时,另一个线程必须等待。只有当使用临界资源的进程退出临界区后,这个进程才会解除阻塞状态。
例如线程B需要访问打印机,但此时线程A占用了打印机,进程B会被阻塞,直到进程A释放了打印机资源,进程B才可以继续执行。
3. 同步和互斥实现的手段
在应用程序中,常用的有:
- 临界区(CriticalSection)
- 互斥量(Mutex)
- 信号量(Semaphore)
- 事件(Event)
在内核态多线程编程的时候,同样需要线程的同步与互斥,教科书上介绍了几种:
- 自旋锁(Spinlock):这个当年毕业的时候,在做EMC的笔试的时候,考到了。
- 读写锁(RWLock)
等等,用的不多,不写了。后文会对每种实现进行讲解。
4.同步和互斥的经典问题
- 生产者和消费者问题
- 读者和写着问题
- 哲学家进餐问题