线程共享同一进程的代码段(可以共享)、全局数据段等资源;但有自己的代码段、栈、寄存器等。
一、概念
互斥:
对于多个线程在运行过程中,对共享资源(临界区)不能同时访问,所以引入了互斥的概念。
一个在使用临界资源时,另一个必须等待(阻塞)。
同步:
同步就好⽐:「操作 A 应在操作 B 之前执⾏」,「操作 C 必须在操作 A 和操作 B 都完成之后才能执⾏」等;
二、实现互斥/同步方法:
1.锁:加锁、解锁(只能实现互斥)
(1)忙等待锁(自旋锁)
cpu提供的原子操作指令--Test-and-set
操作系统实现:
在访问临界资源前,调用lock,出临界区时调用unlock。
(2)无等待锁
2.信号量:P V操作
信号量表示资源的数量,对应一个整形变量。P 操作是⽤在进⼊临界区之前,V 操作是⽤在离开临界区之后,这两个操作是必须成对出现的。
在操作系统中的实现:
(1)实现互斥
设信号量s初值为1,只要把进⼊临界区的操作置于 P(s) 和 V(s) 之间,即可实现进程/线程互斥:
(2)实现同步
设信号量s初值为0。
生产者消费者案例:
分析:1. 生产者和消费者对缓冲区的访问是互斥的,所以需要互斥量mutex=1
2.消费者只有在生产者生产完成,才能读取数据,需要同步量full = 0
3.生产者在缓冲区有空位时才可以写数据,需要信号量empty=n,表示资源
执行过程:
producer() consumer()
{ {
P(empty);//资源数减1 P(full);
P(mutex);//互斥访问缓冲区 P(mutex);
放入数据 读数据
V(mutex);//退出缓存区 V(mutex);//退出缓存区
V(full );//缓冲区内容量加1 V(empty)
}
注意:消费者执行 P(empty);生产者执行P(full)要在P(mutex)之前