Linux 什么时候应该使用互斥量,什么时候应该使用信号量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4039899/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:46:55  来源:igfitidea点击:

When should we use mutex and when should we use semaphore

linuxmultithreadingsynchronizationmutexsemaphore

提问by Karthik Balaguru

When should we use mutex and when should we use semaphore ?

我们什么时候应该使用互斥锁,什么时候应该使用信号量?

回答by paxdiablo

A mutex is a mutual exclusion object, similarto a semaphore but that only allows one locker at a time and whose ownership restrictions may be more stringent than a semaphore.

互斥体是一种互斥对象,类似于信号量,但一次只允许一个储物柜,其所有权限制可能比信号量更严格。

It can be thought of as equivalent to a normal counting semaphore (with a count of one) and the requirement that it can only be released by the same thread that locked it(a).

它可以被认为等同于一个普通的计数信号量(计数为 1),并且要求它只能由锁定它的同一个线程释放(a)

A semaphore, on the other hand, has an arbitrary count and can be locked by that many lockers concurrently. And it may not have a requirement that it be released by the same thread that claimed it (but, if not, you have to carefully track who currently has responsibility for it, much like allocated memory).

另一方面,信号量具有任意数量,并且可以同时被许多储物柜锁定。并且它可能不要求它由声明它的同一线程释放(但是,如果没有,您必须仔细跟踪当前负责它的人,就像分配的内存一样)。

So, if you have a number of instances of a resource (say three tape drives), you could use a semaphore with a count of 3. Note that this doesn't tell you which of those tape drives you have, just that you have a certain number.

因此,如果您有多个资源实例(比如三个磁带驱动器),您可以使用计数为 3 的信号量。请注意,这不会告诉您您拥有哪些磁带驱动器,只是告诉您一定数量。

Also with semaphores, it's possible for a single locker to lock multiple instances of a resource, such as for a tape-to-tape copy. If you have one resource (say a memory location that you don't want to corrupt), a mutex is more suitable.

同样使用信号量,单个储物柜可以锁定资源的多个实例,例如磁带到磁带的复制。如果您有一个资源(比如您不想破坏的内存位置),则互斥锁更合适。

Equivalent operations are:

等效操作是:

Counting semaphore          Mutual exclusion semaphore
--------------------------  --------------------------
  Claim/decrease (P)                  Lock
  Release/increase (V)                Unlock

Aside:in case you've ever wondered at the bizarre letters used for claiming and releasing semaphores, it's because the inventor was Dutch. Probeer te verlagen means to try and decrease while verhogen means to increase.

旁白:如果您曾经对用于声明和释放信号量的奇怪字母感到疑惑,那是因为发明者是荷兰人。Probeer te verlagen 意味着尝试减少,而 verhogen 意味着增加。



(a)... or it can be thought of as something totally distinct from a semaphore, which may be safer given their almost-always-different uses.

(a)... 或者它可以被认为是与信号量完全不同的东西,考虑到它们几乎总是不同的用途,信号量可能更安全。

回答by Omnifarious

As was pointed out, a semaphore with a count of one is the same thing as a 'binary' semaphore which is the same thing as a mutex.

正如所指出的,计数为 1 的信号量与“二进制”信号量相同,后者与互斥量相同。

The main things I've seen semaphores with a count greater than one used for is producer/consumer situations in which you have a queue of a certain fixed size.

我所看到的计数大于 1 的信号量主要用于生产者/消费者情况,在这种情况下,您有一个固定大小的队列。

You have two semaphores then. The first semaphore is initially set to be the number of items in the queue and the second semaphore is set to 0. The producer does a P operation on the first semaphore, adds to the queue. and does a V operation on the second. The consumer does a P operation on the second semaphore, removes from the queue, and then does a V operation on the first.

那么你有两个信号量。第一个信号量最初设置为队列中的项目数,第二个信号量设置为 0。生产者对第一个信号量执行 P 操作,添加到队列中。并对第二个进行 V 操作。消费者对第二个信号量执行 P 操作,从队列中移除,然后对第一个信号量执行 V 操作。

In this way the producer is blocked whenever it fills the queue, and the consumer is blocked whenever the queue is empty.

这样生产者在队列填满时被阻塞,而消费者在队列为空时被阻塞。

回答by Patrick Schlüter

While @opaxdiablo answer is totally correct I would like to point out that the usage scenario of both things is quite different. The mutex is used for protecting parts of code from running concurrently, semaphores are used for one thread to signal another thread to run.

虽然@opaxdiablo 的回答是完全正确的,但我想指出这两种东西的使用场景是完全不同的。互斥锁用于保护部分代码不被并发运行,信号量用于一个线程向另一个线程发出信号以使其运行。

/* Task 1 */
pthread_mutex_lock(mutex_thing);
    // Safely use shared resource
pthread_mutex_unlock(mutex_thing);



/* Task 2 */
pthread_mutex_lock(mutex_thing);
   // Safely use shared resource
pthread_mutex_unlock(mutex_thing); // unlock mutex

The semaphore scenario is different:

信号量场景不同:

/* Task 1 - Producer */
sema_post(&sem);   // Send the signal

/* Task 2 - Consumer */
sema_wait(&sem);   // Wait for signal

See http://www.netrino.com/node/202for further explanations

有关进一步说明,请参阅http://www.netrino.com/node/202

回答by fornwall

See "The Toilet Example" - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm:

参见“厕所示例” - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm

Mutex:

互斥体:

Is a key to a toilet. One person can have the key - occupy the toilet - at the time. When finished, the person gives (frees) the key to the next person in the queue.

是厕所的钥匙。一个人可以拥有钥匙——占用厕所——当时。完成后,此人将钥匙交给(释放)队列中的下一个人。

Officially: "Mutexes are typically used to serialise access to a section of re-entrant code that cannot be executed concurrently by more than one thread. A mutex object only allows one thread into a controlled section, forcing other threads which attempt to gain access to that section to wait until the first thread has exited from that section." Ref: Symbian Developer Library

官方称:“互斥锁通常用于序列化对不能由多个线程同时执行的可重入代码部分的访问。互斥锁对象只允许一个线程进入受控部分,迫使其他试图获得访问权限的线程该部分等待,直到第一个线程从该部分退出。” 参考:Symbian 开发者库

(A mutex is really a semaphore with value 1.)

(互斥锁实际上是一个值为 1 的信号量。)

Semaphore:

信号:

Is the number of free identical toilet keys. Example, say we have four toilets with identical locks and keys. The semaphore count - the count of keys - is set to 4 at beginning (all four toilets are free), then the count value is decremented as people are coming in. If all toilets are full, ie. there are no free keys left, the semaphore count is 0. Now, when eq. one person leaves the toilet, semaphore is increased to 1 (one free key), and given to the next person in the queue.

是免费的相同厕所钥匙的数量。例如,假设我们有四个带有相同锁和钥匙的马桶。信号量计数 - 钥匙的数量 - 开始时设置为 4(所有四个厕所都是免费的),然后随着人们进来,计数值递减。如果所有厕所都满了,即。没有剩余的空闲键,信号量计数为 0。现在,当 eq。一个人离开厕所,信号量增加到1(一个空闲键),并给队列中的下一个人。

Officially: "A semaphore restricts the number of simultaneous users of a shared resource up to a maximum number. Threads can request access to the resource (decrementing the semaphore), and can signal that they have finished using the resource (incrementing the semaphore)." Ref: Symbian Developer Library

官方称:“信号量将共享资源的同时用户数量限制为最大数量。线程可以请求访问资源(递减信号量),并可以发出信号表示它们已完成使用资源(递增信号量)。 ” 参考:Symbian 开发者库

回答by Peer Stritzinger

It is very important to understand that a mutex is nota semaphore with count 1!

了解互斥锁不是计数为 1 的信号量非常重要!

This is the reason there are things like binary semaphores (which are really semaphores with count 1).

这就是为什么有像二进制信号量这样的东西(它们实际上是计数为 1 的信号量)的原因。

The difference between a Mutex and a Binary-Semaphore is the principle of ownership:

Mutex 和 Binary-Semaphore 之间的区别在于所有权原则:

A mutex is acquired by a task and therefore must also be released by the same task. This makes it possible to fix several problems with binary semaphores (Accidential release, recursive deadlock and priority inversion).

互斥锁由任务获取,因此也必须由同一任务释放。这使得可以修复二进制信号量的几个问题(意外释放、递归死锁和优先级反转)。

Caveat: I wrote "makes it possible", if and how these problems are fixed is up to the OS implementation.

警告:我写了“使之成为可能”,这些问题是否以及如何解决取决于操作系统的实现。

Because the mutex is has to be released by the same task it is not very good for synchronization of tasks. But if combined with condition variables you get very powerful building blocks for building all kinds of ipc primitives.

由于互斥量必须由同一任务释放,因此对于任务同步来说不是很好。但是如果结合条件变量,您将获得非常强大的构建块,用于构建各种 ipc 原语。

So my recommendation is: if you got cleanly implemented mutexes and condition variables (like with POSIX pthreads) use these.

所以我的建议是:如果你有干净地实现的互斥体和条件变量(如 POSIX pthreads),请使用这些。

Use semaphores only if they fit exactly to the problem you are trying to solve, don't try to build other primitives (e.g. rw-locks out of semaphores, use mutexes and condition variables for these)

仅当信号量完全适合您要解决的问题时才使用它们,不要尝试构建其他原语(例如,使用信号量的 rw 锁,为这些使用互斥锁和条件变量)

There is a lot of misunderstanding mutexes and semaphores. The best explanation I found so far is in this 3-Part article:

有很多误解互斥体和信号量。到目前为止,我找到的最好的解释是这篇由 3 部分组成的文章:

Mutex vs. Semaphores – Part 1: Semaphores

互斥量与信号量 - 第 1 部分:信号量

Mutex vs. Semaphores – Part 2: The Mutex

互斥体与信号量 – 第 2 部分:互斥体

Mutex vs. Semaphores – Part 3 (final part): Mutual Exclusion Problems

互斥与信号量——第 3 部分(最后一部分):互斥问题

回答by Annu Gogatya

Here is how I remember when to use what -

这是我记得何时使用什么 -

Semaphore:Use a semaphore when you (thread) want to sleep till some other thread tells you to wake up. Semaphore 'down' happens in one thread (producer) and semaphore 'up' (for same semaphore) happens in another thread (consumer) e.g.: In producer-consumer problem, producer wants to sleep till at least one buffer slot is empty - only the consumer thread can tell when a buffer slot is empty.

信号量:当您(线程)想要睡眠直到其他线程告诉您醒来时,请使用信号量。信号量“向下”发生在一个线程(生产者)中,而信号量“向上”(对于同一个信号量)发生在另一个线程(消费者)中,例如:在生产者-消费者问题中,生产者想要休眠,直到至少一个缓冲区为空 - 仅消费者线程可以判断缓冲槽何时为空。

Mutex:Use a mutex when you (thread) want to execute code that should not be executed by any other thread at the same time. Mutex 'down' happens in one thread and mutex 'up' musthappen in the same thread later on. e.g.: If you are deleting a node from a global linked list, you do not want another thread to muck around with pointers while you are deleting the node. When you acquire a mutex and are busy deleting a node, if another thread tries to acquire the same mutex, it will be put to sleep till you release the mutex.

互斥锁:当您(线程)想要执行不应由任何其他线程同时执行的代码时,请使用互斥锁。互斥“向下”发生在一个线程中,而互斥“向上”稍后必须发生在同一线程中。例如:如果您要从全局链表中删除一个节点,则在删除该节点时,您不希望另一个线程乱用指针。当您获取互斥锁并忙于删除节点时,如果另一个线程尝试获取相同的互斥锁,它将进入休眠状态,直到您释放该互斥锁。

Spinlock:Use a spinlock when you really want to use a mutex but your thread is not allowed to sleep. e.g.: An interrupt handler within OS kernel must never sleep. If it does the system will freeze / crash. If you need to insert a node to globally shared linked list from the interrupt handler, acquire a spinlock - insert node - release spinlock.

自旋锁:使用一个自旋锁,当你真的想用一个互斥体,但你的线程不允许睡觉。例如:操作系统内核中的中断处理程序绝不能休眠。如果这样做,系统将冻结/崩溃。如果需要从中断处理程序向全局共享链表中插入节点,获取自旋锁-插入节点-释放自旋锁。

回答by Ajeet Ganga

Trying not to sound zany, but can't help myself.

尽量不要听起来很滑稽,但无法帮助自己。

Your question should be what is the difference between mutex and semaphores ? And to be more precise question should be, 'what is the relationship between mutex and semaphores ?'

您的问题应该是 mutex 和 semaphores 之间有什么区别?更准确的问题应该是,“互斥体和信号量之间的关系是什么?”

(I would have added that question but I'm hundred % sure some overzealous moderator would close it as duplicate without understanding difference between difference and relationship.)

(我会添加这个问题,但我 100% 肯定某些过分热心的版主会在不理解差异和关系之间的区别的情况下将其关闭为重复的。)

In object terminology we can observe that :

在对象术语中,我们可以观察到:

observation.1 Semaphore contains mutex

观察.1 信号量包含互斥体

observation.2 Mutex is not semaphore and semaphore is not mutex.

观察.2 互斥量不是信号量,信号量也不是互斥量。

There are some semaphores that will act as if they are mutex, called binary semaphores, but they are freaking NOT mutex.

有一些信号量就像互斥体一样,称为二元信号量,但它们不是互斥体。

There is a special ingredient called Signalling (posix uses condition_variable for that name), required to make a Semaphore out of mutex. Think of it as a notification-source. If two or more threads are subscribed to same notification-source, then it is possible to send them message to either ONE or to ALL, to wakeup.

有一种特殊的成分叫做 Signaling(posix 使用 condition_variable 作为该名称),需要使用互斥锁来制作信号量。将其视为通知源。如果两个或多个线程订阅了相同的通知源,则可以将消息发送给 ONE 或 ALL 以唤醒它们。

There could be one or more counters associated with semaphores, which are guarded by mutex. The simple most scenario for semaphore, there is a single counter which can be either 0 or 1.

可能有一个或多个计数器与信号量相关联,由互斥锁保护。最简单的信号量场景,有一个计数器可以是 0 或 1。

This is where confusion pours in like monsoon rain.

这是混乱如季风雨般倾泻而下的地方。

A semaphore with a counter that can be 0 or 1 is NOT mutex.

计数器可以为 0 或 1 的信号量不是互斥锁。

Mutex has two states (0,1) and one ownership(task). Semaphore has a mutex, some counters and a condition variable.

Mutex 有两种状态(0,1)和一种所有权(任务)。信号量有一个互斥锁、一些计数器和一个条件变量。

Now, use your imagination, and every combination of usage of counter and when to signal can make one kind-of-Semaphore.

现在,发挥你的想象力,计数器的每种用法和何时发出信号的组合都可以构成一种信号量。

  1. Single counter with value 0 or 1 and signaling when value goes to 1 AND then unlocks one of the guy waiting on the signal == Binary semaphore

  2. Single counter with value 0 to N and signaling when value goes to less than N, and locks/waits when values is N == Counting semaphore

  3. Single counter with value 0 to N and signaling when value goes to N, and locks/waits when values is less than N == Barrier semaphore (well if they dont call it, then they should.)

  1. 值为 0 或 1 的单个计数器并在值变为 1 时发出信号,然后解锁等待信号的人之一 == 二进制信号量

  2. 值为 0 到 N 的单个计数器并在值小于 N 时发出信号,并在值为 N == 计数信号量时锁定/等待

  3. 值为 0 到 N 的单个计数器并在值变为 N 时发出信号,并在值小于 N == Barrier 信号量时锁定/等待(如果他们不调用它,那么他们应该调用它。)

Now to your question, when to use what. (OR rather correct question version.3 when to use mutex and when to use binary-semaphore, since there is no comparison to non-binary-semaphore.) Use mutex when 1. you want a customized behavior, that is not provided by binary semaphore, such are spin-lock or fast-lock or recursive-locks. You can usually customize mutexes with attributes, but customizing semaphore is nothing but writing new semaphore. 2. you want lightweight OR faster primitive

现在你的问题,什么时候使用什么。(或相当正确的问题 version.3 何时使用互斥量以及何时使用二进制信号量,因为与非二进制信号量没有比较。)当 1. 您想要自定义行为时使用互斥量,这是二进制不提供的信号量,例如自旋锁或快速锁或递归锁。您通常可以使用属性自定义互斥锁,但是自定义信号量只不过是编写新的信号量。2.你想要轻量级或更快的原语

Use semaphores, when what you want is exactly provided by it.

使用信号量,当你想要的东西完全由它提供时。

If you dont understand what is being provided by your implementation of binary-semaphore, then IMHO, use mutex.

如果您不了解二进制信号量的实现提供了什么,那么恕我直言,请使用互斥锁。

And lastly read a book rather than relying just on SO.

最后阅读一本书,而不是仅仅依赖于 SO。

回答by Saurabh Sengar

I think the question should be the difference between mutex and binary semaphore.

我认为问题应该是互斥量和二进制信号量之间的区别。

Mutex = It is a ownership lock mechanism, only the thread who acquire the lock can release the lock.

Mutex = 它是一种所有权锁机制,只有获得锁的线程才能释放锁。

binary Semaphore = It is more of a signal mechanism, any other higher priority thread if want can signal and take the lock.

二进制信号量 = 它更像是一种信号机制,如果需要,任何其他更高优先级的线程都可以发出信号并获取锁。

回答by Frode Akselsen

A mutex is a special case of a semaphore. A semaphore allows several threads to go into the critical section. When creating a semaphore you define how may threads are allowed in the critical section. Of course your code must be able to handle several accesses to this critical section.

互斥体是信号量的特例。信号量允许多个线程进入临界区。创建信号量时,您可以定义临界区中允许线程的数量。当然,您的代码必须能够处理对该临界区的多次访问。

回答by Yves

Mutex is to protect the shared resource.
Semaphore is to dispatch the threads.

Mutex 是为了保护共享资源。
信号量用于调度线程。

Mutex:
Imagine that there are some tickets to sell. We can simulate a case where many people buy the tickets at the same time: each person is a thread to buy tickets. Obviously we need to use the mutex to protect the tickets because it is the shared resource.

Mutex:
想象一下,有一些门票要卖。我们可以模拟多人同时购票的情况:每个人都是一个线程来买票。显然我们需要使用互斥锁来保护票证,因为它是共享资源。


Semaphore:
Imagine that we need to do a calculation as below:


信号量:
想象一下我们需要做如下计算:

c = a + b;

Also, we need a function geta()to calculate a, a function getb()to calculate band a function getc()to do the calculation c = a + b.

此外,我们需要一个函数geta()来计算a,函数getb()计算b和功能getc()做计算c = a + b

Obviously, we can't do the c = a + bunless geta()and getb()have been finished.
If the three functions are three threads, we need to dispatch the three threads.

显然,我们不能做c = a + b除非geta()getb()已经完成。
如果这三个函数是三个线程,我们需要分派这三个线程。

int a, b, c;
void geta()
{
    a = calculatea();
    semaphore_increase();
}

void getb()
{
    b = calculateb();
    semaphore_increase();
}

void getc()
{
    semaphore_decrease();
    semaphore_decrease();
    c = a + b;
}

t1 = thread_create(geta);
t2 = thread_create(getb);
t3 = thread_create(getc);
thread_join(t3);

With the help of the semaphore, the code above can make sure that t3won't do its job untill t1and t2have done their jobs.

随着信号的帮助下,上面的代码可以确保t3不会做其工作,直到t1t2做他们的工作。

In a word, semaphore is to make threads execute as a logicial order whereas mutex is to protect shared resource.
So they are NOT the same thing even if some people always say that mutex is a special semaphore with the initial value 1. You can say like this too but please notice that they are used in different cases. Don't replace one by the other even if you can do that.

总之,信号量是让线程按照逻辑顺序执行,而互斥量是为了保护共享资源。
所以即使有人总是说互斥是一个特殊的信号量,初始值为1,它们也不是一回事。你也可以这样说,但请注意它们用于不同的情况。即使你能做到,也不要用另一个替换。