操作系统 mutex互斥锁 vs semaphore信号量
根据操作系统术语,互斥锁和信号量是提供同步服务的内核资源,也被称为 同步原语 。进程同步在维护共享数据一致性方面起着重要作用。在处理关键区域问题时既有软件解决方案,也有硬件解决方案。但是硬件解决关键区域问题的方法较难实现。互斥锁和信号量都提供同步服务,但它们并不相同。
什么是互斥锁
互斥锁是一种互斥对象,用于同步访问资源。它在程序开始时使用唯一名称创建。互斥锁锁定机制确保只有一个线程可以获取互斥锁并进入关键区域。该线程只有在退出关键区域时才释放互斥锁。
这是一种用于控制对共享资源访问的特殊类型的二进制信号量。它包含了一个优先级继承机制,以避免延长的优先级逆转问题。它允许当前较高优先级的任务在阻塞状态下保持最短的时间。然而,优先级继承并不会纠正优先级逆转,而只是最小化其影响。
示例
以下是一个示例来说明这种情况,
wait (mutex);
.....
Critical Section
.....
signal (mutex);
互斥锁的使用
互斥锁提供互斥操作,生产者和消费者可以拥有互斥锁,并进行它们的工作。只要生产者在填充缓冲区时,用户需要等待,反之亦然。在互斥锁锁定期间,只有一个线程可以与整个缓冲区一起工作。
当程序启动时,它请求系统为给定资源创建一个互斥锁对象。系统使用唯一的名称或ID创建互斥锁对象。当程序线程想要使用资源时,它占用互斥锁对象上的锁,利用资源,并在使用后释放互斥锁对象的锁。然后下一个进程被允许获取互斥锁对象上的锁。
同时,一个进程已经获得了互斥锁对象上的锁,其他线程或进程无法访问该资源。如果互斥锁对象已被锁定,则希望获取互斥锁对象上的锁的进程必须等待,并被系统排队,直到互斥锁对象被解锁。
互斥锁的优势
互斥锁具有以下优势:
- 互斥锁只是在进入其临界区之前获取的简单锁,并在之后释放。
- 由于任何给定时间只有一个线程处于其临界区中,因此不存在竞争条件,数据始终保持一致。
互斥锁的缺点
互斥锁也有一些缺点,例如:
- 如果一个线程获取锁并进入睡眠或者被抢占,那么另一个线程可能无法继续执行,这可能导致饥饿。
- 它无法从不同于获取它的上下文中锁定或解锁。
- 一次只允许一个线程进入临界区。
- 普通实现可能导致繁忙等待状态,从而浪费CPU时间。
什么是信号量
信号量只是一个非负的在线程之间共享的变量。信号量是一种信号机制,另一个线程可以向等待信号量的线程发送信号。
信号量使用两个原子操作,
1. 等待: 等待操作会将其参数 S 的值减小,如果它是正数。如果 S 是负数或零,则不执行任何操作。
wait(S)
{
while (S<=0);
S--;
}
2. 用于进程同步的信号: 信号操作会将其参数S的值增加。
signal(S)
{
S++;
}
信号量用于根据其设置情况,允许或拒绝访问资源。
使用信号量
对于单个缓冲区,可以将4KB缓冲区分成四个1KB的缓冲区。可以将信号量与这四个缓冲区关联起来,允许用户和生产者同时在不同的缓冲区上工作。
信号量的类型
操作系统将信号量分为两类 计数信号量 和 二进制信号量 。
1. 计数信号量: 信号量S的值初始化为系统中存在的 资源数量 。当一个进程想要访问资源时,它对信号量执行 等待(wait) 操作,并将信号量值减一。当它释放资源时,它对信号量执行 信号(signal) 操作,并将信号量值增加一。
当信号量计数为0时,表示进程占用所有资源。进程在信号量计数为0时需要使用资源。它执行 等待(wait) 操作,并被 阻塞(blocked) ,直到信号量值大于0为止。
2. 二进制信号量: 信号量的值范围在 0 和 1 之间。它类似于互斥锁,但互斥锁是一种锁定机制,而信号量是一种信号机制。在二进制信号量中,如果一个进程想要访问资源,它会对信号量执行 等待(wait()) 操作,并将信号量的值从1减少到0。当它释放资源时,它会对信号量执行 信号(signal()) 操作,并将其值增加到1。假设信号量的值为0,并且一个进程想要访问该资源。在这种情况下,它会执行 等待(wait()) 操作,并阻塞自己,直到当前正在使用资源的进程释放资源。
信号量的优势
以下是信号量的优势:
- 允许多个线程访问临界区
- 信号量与机器无关
- 信号量在微内核的机器无关代码中进行实现
- 不允许多个进程进入临界区
- 由于信号量中存在忙等待,因此不会浪费进程时间和资源
- 它们是机器无关的,应该在微内核的机器无关代码中运行
- 它们允许灵活管理资源
信号量的缺点
信号量也有一些缺点,例如:
- 信号量最大的限制之一是优先级反转
- 操作系统必须追踪对信号量的所有调用
- 它们的使用并不强制执行,仅仅是通过约定
- 等待和通知操作必须按正确的顺序执行,以避免信号量死锁
- 信号量编程是一种复杂的方法,因此存在无法实现互斥的机会
- 对于大规模使用而言,信号量也不是一种实际可行的方法,因为使用它们会导致模块化的损失
- 信号量更容易出现程序员错误,并且可能由于程序员错误导致死锁或互斥违规
互斥锁和信号量的区别
互斥锁和信号量的基本区别在于,信号量是一种信号机制,即进程执行wait()和signal()操作以指示它们是否正在获取或释放资源。相反,互斥锁是一种锁定机制,进程必须在互斥锁对象上获取锁定,如果希望获取资源。以下是信号量和互斥锁之间的其他区别:
术语 | 互斥锁 | 信号量 |
---|---|---|
定义 | 互斥锁是一种锁定机制,进程需要锁定互斥锁对象才能获取资源,释放资源时需要解锁互斥锁对象。 | 信号量是一种信号机制,对信号量变量执行wait()和signal()操作指示进程是否正在获取或释放资源。 |
存在形式 | 互斥锁是一个对象。 | 信号量是一个整数变量。 |
功能 | 互斥锁允许多个程序线程访问同一资源,但不能同时访问。 | 信号量允许多个程序线程访问资源的有限实例。 |
拥有权 | 互斥锁对象的锁定只能由已经获取互斥锁的进程释放。 | 任何获取或释放资源的进程可以通过执行wait()和signal()操作来更改信号量的值。 |
分类 | 互斥锁不进行进一步分类。 | 信号量可以分为计数信号量和二进制信号量。 |
操作方法 | 进程通过请求或释放资源来锁定或解锁互斥锁对象。 | 信号量的值在初始化以外还可以通过wait()和signal()操作进行修改。 |
占用的资源 | 如果互斥锁对象已经被锁定,则希望获取资源的进程将等待并由系统排队,直到资源被释放并且互斥锁对象解锁。 | 假设进程获取了所有的资源,没有空闲资源。在这种情况下,希望获取资源的进程将在信号量变量上执行wait()操作,阻塞自己,直到信号量的计数变为大于0。 |