互斥锁与信号量 – 它们之间的区别
Mutex与Semaphore的关键区别
- Mutex是锁定机制,而Semaphore是信号机制
- Mutex只是一个对象,而Semaphore是一个整数
- Mutex没有子类型,而Semaphore有两种类型:计数信号量和二元信号量。
- Semaphore支持wait和signal操作的修改,而Mutex只能由可能请求或释放资源的进程修改。
- Semaphore的值使用wait()和signal()操作进行修改,另一方面,Mutex的操作是锁定或解锁。

在这里,我分析了Mutex和Semaphore之间的区别,并将全面评估它们的优缺点。
关于Mutex和Semaphore的常见事实
根据我的实践,以下是关于Mutex与Semaphore的一些常见事实
- 只有一个任务可以获取互斥锁。因此,互斥锁具有所有权,只有所有者才能释放它。
- 使用互斥锁和信号量的原因不同,也许因为它们的实现相似,互斥锁可以被视为二元信号量。
- 一个广为人知的误解是,互斥锁和信号量几乎相同,唯一的区别是互斥锁能够计数到1,而信号量能够从0计数到N。
- 二元信号量和互斥锁之间总是不确定。你可能会听说互斥锁是二元信号量,这是不正确的。
什么是Semaphore?
信号量仅仅是线程之间共享的非负变量。信号量是信号机制,等待信号量的线程可以被另一个线程信号。它使用两个原子操作,1)wait和2)signal进行进程同步。
一个信号量根据其设置方式,允许或禁止对资源的访问。
Semaphore的用途
在单个缓冲区的情况下,我们可以将4 KB的缓冲区分成四个1 KB的缓冲区。信号量可以与这四个缓冲区关联。这允许用户和生产者同时处理不同的缓冲区。
Semaphore的优点
根据我的实践,以下是使用信号量的关键优点
- 它允许多个线程访问临界区
- 信号量是机器无关的。
- 信号量在微内核的机器无关代码中实现。
- 它们不允许多个进程进入临界区。
- 由于信号量中存在忙等待调度,因此从不浪费进程时间和资源。
- 它们是机器无关的,应该在微内核的机器无关代码中运行。
- 它们允许灵活管理资源。
Semaphore的缺点
以下是我遇到的信号量的一些缺点。
- 信号量最大的限制之一是优先级反转。
- 操作系统必须跟踪对wait和signal信号量的所有调用。
- 它们的使用从未被强制执行,而只是约定俗成。
- 为了避免信号量中的死锁,wait和signal操作需要按正确的顺序执行。
- 信号量编程是一种复杂的方法,因此可能无法实现互斥。
- 它也不是大规模使用的实用方法,因为它们的使用会导致模块化丢失。
- 信号量更容易出现程序员错误。
- 它可能由于程序员错误而导致死锁或违反互斥。
什么是Mutex?
Mutex的完整形式是Mutual Exclusion Object(互斥对象)。它是一种特殊的二元信号量,用于控制对共享资源的访问。它包括优先级继承机制,以避免扩展的优先级反转问题。它允许当前优先级较高的任务被阻塞的时间尽可能短。然而,优先级继承并不能纠正优先级反转,只能最大限度地减小其影响。
Mutex的用途
互斥锁提供互斥,无论是生产者还是消费者都可以获得密钥(互斥锁)并继续工作。只要生产者填充缓冲区,用户就需要等待,反之亦然。在Mutex锁定中,所有时候,只有一个线程可以处理整个缓冲区。
Mutex的优点
根据我的观察,以下是Mutex的关键优势
- 互斥锁只是简单的锁定,在进入其临界区之前获取,然后释放它。
- 由于任何时候只有一个线程在其临界区中,因此没有竞态条件,数据始终保持一致。
Mutex的缺点
在我的实践中,我发现Mutex有几个缺点。
- 如果一个线程获取了锁并进入休眠状态,或者它被抢占了,那么另一个线程可能无法继续前进。这可能导致饿死。
- 它不能从获取它的上下文之外的上下文锁定或解锁。
- 一次只允许一个线程进入临界区。
- 正常的实现可能导致忙等待状态,浪费CPU时间。
Semaphore与Mutex的区别
根据我学习的经验,Mutex和Semaphore的区别如下:
参数 | Semaphore | 互斥锁 (Mutex) |
---|---|---|
机制 | 它是一种信号机制。 | 它是一种锁定机制。 |
数据类型 | Semaphore是一个整数变量。 | Mutex只是一个对象。 |
修改 | wait和signal操作可以修改信号量。 | 它仅由可能请求或释放资源的进程修改。 |
资源管理 | 如果没有可用的资源,则需要资源的进程应该执行wait操作。它应该等到信号量计数大于0。 | 如果它被锁定,进程必须等待。进程应排队。这仅在互斥锁解锁时才需要访问。 |
线程 | 您可以拥有多个程序线程。 | 您可以拥有多个程序线程,但在mutex中不能同时拥有。 |
所有权 | 值可以由任何释放或获取资源的进程更改。 | 对象锁仅由获取锁的进程释放。 |
类型 | Semaphore的类型是计数信号量和二元信号量。 | Mutex没有子类型。 |
操作 | Semaphore值使用wait()和signal()操作进行修改。 | Mutex对象被锁定或解锁。 |
资源占用 | 如果所有资源都被使用,并且请求资源的进程执行wait()操作并阻塞自身,直到信号量计数变为>1,则会被占用。 | 如果对象已被锁定,则请求资源的进程会等待,并在锁释放之前由系统排队。 |
结论
根据我的经验,选择互斥锁和信号量的关键在于认识到它们的操作细微差别。信号量非常适合复杂的同步,而互斥锁则适用于简单的互斥,在更简单的环境中确保资源安全。