二进制信号量和互斥量之间有区别吗?或者它们本质上是相同的?
当前回答
神话:
一些文章说“二进制信号量和互斥量是相同的”或“值为1的信号量是互斥量”,但基本的区别是互斥量只能由获得它的线程释放,而你可以从任何其他线程发出信号量
重点:
一个线程可以获得多个锁(互斥锁)。
只有递归互斥锁才能被锁多次,这里的锁和锁应该是一样的
•如果一个线程已经锁定了一个互斥锁,试图再次锁定互斥锁,它将进入该互斥锁的等待列表,这将导致死锁。
二进制信号量和互斥量相似但不相同。
互斥是昂贵的操作,因为与它相关的保护协议。
互斥的主要目的是实现对资源的原子访问或锁定
其他回答
正如这里许多人提到的,互斥锁用于保护关键代码段(又名临界段)。你将在同一个线程中获得互斥锁(lock),进入临界区,释放互斥锁(unlock)。
在使用信号量时,您可以让一个线程(例如线程a)等待一个信号量,直到另一个线程(例如线程B)完成任何任务,然后为线程a设置信号量以停止等待,并继续其任务。
在理论层面上,它们在语义上并无不同。您可以使用信号量实现互斥量,反之亦然(参见这里的示例)。在实践中,实现是不同的,它们提供的服务也略有不同。
实际的区别(就围绕它们的系统服务而言)在于互斥锁的实现旨在成为一种更轻量级的同步机制。在oracle语言中,互斥锁被称为锁存器,而信号量被称为等待。
在最低级别,他们使用某种原子测试和设置机制。它读取内存位置的当前值,计算某种条件,并在一条不能中断的指令中写入该位置的值。这意味着您可以获得一个互斥锁,并测试是否有人在您之前拥有它。
典型的互斥量实现有一个进程或线程执行test-and-set指令,并评估是否有其他东西设置了互斥量。这里的关键点是与调度程序没有交互,因此我们不知道(也不关心)谁设置了锁。然后,我们要么放弃我们的时间片,并在任务重新调度时再次尝试它,要么执行自旋锁。自旋锁是这样一种算法:
Count down from 5000:
i. Execute the test-and-set instruction
ii. If the mutex is clear, we have acquired it in the previous instruction
so we can exit the loop
iii. When we get to zero, give up our time slice.
当我们完成执行受保护的代码(称为临界区)时,我们只需将互斥量的值设置为零或其他表示“清除”的值。如果有多个任务试图获取互斥量,那么下一个计划在互斥量释放后的任务将获得对资源的访问权。通常情况下,您可以使用互斥来控制同步资源,在这种资源中,只需要在很短的时间内对其进行独占访问,通常是对共享数据结构进行更新。
A semaphore is a synchronised data structure (typically using a mutex) that has a count and some system call wrappers that interact with the scheduler in a bit more depth than the mutex libraries would. Semaphores are incremented and decremented and used to block tasks until something else is ready. See Producer/Consumer Problem for a simple example of this. Semaphores are initialised to some value - a binary semaphore is just a special case where the semaphore is initialised to 1. Posting to a semaphore has the effect of waking up a waiting process.
一个基本的信号量算法如下所示:
(somewhere in the program startup)
Initialise the semaphore to its start-up value.
Acquiring a semaphore
i. (synchronised) Attempt to decrement the semaphore value
ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.
Posting a semaphore
i. (synchronised) Increment the semaphore value
ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.
iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.
在二进制信号量的情况下,两者之间的主要实际区别是围绕实际数据结构的系统服务的性质。
编辑:正如evan正确地指出的那样,自旋锁会降低单个处理器的速度。你只能在多处理器上使用自旋锁,因为在单处理器上,持有互斥锁的进程永远不会在另一个任务运行时重置它。自旋锁只在多处理器架构上有用。
你可以通过以下方法清楚地记住不同之处:
互斥锁:用于保护关键区域, 互斥锁不能跨进程使用,只能在单个进程中使用 信号量:用于信号资源的可用性。 信号量既可以跨进程使用,也可以跨进程使用。
除了互斥对象有一个所有者之外,这两个对象还可以针对不同的用途进行优化。互斥锁被设计为只保留很短的时间;违反这一点会导致糟糕的性能和不公平的调度。例如,一个正在运行的线程可能被允许获取一个互斥量,即使另一个线程已经被阻塞在这个线程上。信号量可以提供更多的公平性,或者可以使用几个条件变量强制实现公平性。
The basic issue is concurrency. There is more than one flow of control. Think about two processes using a shared memory. Now only one process can access the shared memory at a time. If more than one process accesses the shared memory at a time, the contents of shared memory would get corrupted. It is like a railroad track. Only one train can run on it, else there would be an accident.So there is a signalling mechanism, which a driver checks. If the signal is green, the train can go and if it is red it has to wait to use the track. Similarly in case of shared memory, there is a binary semaphore. If the semaphore is 1, a process acquires it (makes it 0) and goes ahead and accesses it. If the semaphore is 0, the process waits. The functionality the binary semaphore has to provide is mutual exclusion (or mutex, in short) so that only one of the many concurrent entities (process or thread) mutually excludes others. It is a plus that we have counting semaphores, which help in synchronizing multiple instances of a resource.
互斥是信号量提供的基本功能。现在在线程上下文中,我们可能有不同的名称和语法。但基本概念是相同的:如何在并发编程中保持代码和数据的完整性。在我看来,像所有权和相关检查这样的东西是由实现提供的改进。
推荐文章
- 为什么pthreads的条件变量函数需要互斥?
- 并发HashSet<T>在。net框架?
- Trap和中断的区别是什么?
- 互斥实例/教程?
- 为什么Linux被称为单片内核?
- 如何检查Python的操作系统?
- 在Swift中,什么相当于Objective-C的“@synchronized”?
- 信号量和监视器——有什么不同?
- 如何使用JavaScript找到操作系统的详细信息?
- 我如何检查操作系统与预处理器指令?
- 如何在没有操作系统的情况下运行程序?
- 线程之间共享哪些资源?
- Windows、Mac OS X和Linux是用什么语言编写的?
- 什么时候应该使用自旋锁而不是互斥锁?
- context . start前台服务()没有调用service . start前台()