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

时间:2022-09-11 11:45:25

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

何时应该使用互斥量,何时应该使用信号量?

11 个解决方案

#1


71  

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.

信号量:当你(线程)想要睡觉时使用信号量,直到其他线程告诉你要起床。信号量“down”发生在一个线程(生成器)中,信号量“up”(对于相同的信号量)发生在另一个线程(使用者)中,例如:在生产者-使用者问题中,生产者想要休眠至少一个缓冲区槽为空——只有使用者线程可以知道缓冲区槽何时为空。

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' must happen 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.

自旋锁:当您确实需要使用互斥对象时,使用自旋锁,但是线程不允许休眠。例:OS内核中的中断处理程序不能休眠。如果系统崩溃了。如果需要从中断处理程序中插入一个全局共享链表的节点,则获取一个自旋锁-插入节点-释放自旋锁。

#2


48  

A mutex is a mutual exclusion object, similar to 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.

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

#3


38  

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

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

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

这就是为什么会有像二进制信号量这样的东西(它实际上是带有count 1的信号量)。

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

互斥体和二进制信号量之间的区别在于所有权原则:

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:

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

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部分(最后部分):互斥问题

#4


12  

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_lock(mutex_thing);

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/202 for further explanations

详情请见http://www.netrino.com/node/202

#5


8  

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

参见“厕所的例子”——http://pheatt.emporia.edu/courses0/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。现在,当一个人离开厕所时,信号量增加到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开发库

#6


7  

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 ?'

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

(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.)

(我本想补充这个问题,但我百分之百地确信,有些过分热心的版主会在不理解差异和关系之间的差异的情况下,以重复的方式关闭它。)

In object terminology we can observe that :

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

observation.1 Semaphore contains mutex

观察。1信号包含互斥

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

观察。互斥不是信号量,而信号量不是互斥量。

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.

有一种特殊的成分叫信号(posix使用条件变量来命名),需要从互斥量中做出一个信号量。把它看作一个通知源。如果两个或多个线程被订阅到同一个通知源,那么可以将消息发送给其中一个或所有线程,以唤醒它们。

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.

互斥对象有两个状态(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

    一个值为0或1的计数器,当值为1时发出信号,然后解锁一个在信号==二进制信号量上等待的人。

  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

    值为0到N的单计数器,当值小于N时发出信号,当值为N ==计数信号量时,锁定/等待。

  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.)

    值为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

现在你的问题,什么时候用什么。(或者更确切地说是正确的问题版本。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.

最后读一本书,而不是仅仅依靠。

#7


5  

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.

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

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

二进制信号量=它更多的是一种信号机制,任何其他高优先级的线程都可以进行信号和锁定。

#8


2  

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

互斥对象是为了保护共享资源。信号量是分派线程。

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.

互斥:假设有一些票要卖。我们可以模拟这样一种情况:许多人同时购买机票:每个人都是一个购买机票的线程。显然,我们需要使用互斥锁来保护票据,因为它是共享资源。


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 b and a function getc() to do the calculation c = a + b.

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

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

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

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 t3 won't do its job untill t1 and t2 have done their jobs.

在信号量的帮助下,上面的代码可以确保t3不会在t1和t2完成工作之前完成它的工作。

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的特殊信号量。你也可以这样说,但是请注意它们在不同的情况下使用。即使你能做到这一点,也不要把一个取代另一个。

#9


1  

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.

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

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.

通过这种方式,生产者在填充队列时被阻塞,消费者在队列为空时被阻塞。

#10


1  

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.

互斥是信号量的一种特殊情况。信号量允许几个线程进入关键部分。在创建信号量时,定义如何在关键部分中允许线程。当然,您的代码必须能够处理对这个关键部分的几个访问。

#11


0  

All the above answers are of good quality,but this one's just to memorize.The name Mutex is derived from Mutually Exclusive hence you are motivated to think of a mutex lock as Mutual Exclusion between two as in only one at a time,and if I possessed it you can have it only after I release it.On the other hand such case doesn't exist for Semaphore is just like a traffic signal(which the word Semaphore also means).

以上的答案都是很好的,但是这个只是为了记住。互斥对象的名称源自互斥,因此您可以将互斥对象锁看作是两个互斥对象之间的互斥,就像一次只在一个互斥对象之间进行互斥一样。另一方面,这种情况并不存在,因为信号量就像一个交通信号(信号量这个词也有这个意思)。

#1


71  

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.

信号量:当你(线程)想要睡觉时使用信号量,直到其他线程告诉你要起床。信号量“down”发生在一个线程(生成器)中,信号量“up”(对于相同的信号量)发生在另一个线程(使用者)中,例如:在生产者-使用者问题中,生产者想要休眠至少一个缓冲区槽为空——只有使用者线程可以知道缓冲区槽何时为空。

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' must happen 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.

自旋锁:当您确实需要使用互斥对象时,使用自旋锁,但是线程不允许休眠。例:OS内核中的中断处理程序不能休眠。如果系统崩溃了。如果需要从中断处理程序中插入一个全局共享链表的节点,则获取一个自旋锁-插入节点-释放自旋锁。

#2


48  

A mutex is a mutual exclusion object, similar to 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.

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

#3


38  

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

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

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

这就是为什么会有像二进制信号量这样的东西(它实际上是带有count 1的信号量)。

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

互斥体和二进制信号量之间的区别在于所有权原则:

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:

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

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部分(最后部分):互斥问题

#4


12  

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_lock(mutex_thing);

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/202 for further explanations

详情请见http://www.netrino.com/node/202

#5


8  

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

参见“厕所的例子”——http://pheatt.emporia.edu/courses0/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。现在,当一个人离开厕所时,信号量增加到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开发库

#6


7  

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 ?'

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

(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.)

(我本想补充这个问题,但我百分之百地确信,有些过分热心的版主会在不理解差异和关系之间的差异的情况下,以重复的方式关闭它。)

In object terminology we can observe that :

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

observation.1 Semaphore contains mutex

观察。1信号包含互斥

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

观察。互斥不是信号量,而信号量不是互斥量。

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.

有一种特殊的成分叫信号(posix使用条件变量来命名),需要从互斥量中做出一个信号量。把它看作一个通知源。如果两个或多个线程被订阅到同一个通知源,那么可以将消息发送给其中一个或所有线程,以唤醒它们。

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.

互斥对象有两个状态(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

    一个值为0或1的计数器,当值为1时发出信号,然后解锁一个在信号==二进制信号量上等待的人。

  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

    值为0到N的单计数器,当值小于N时发出信号,当值为N ==计数信号量时,锁定/等待。

  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.)

    值为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

现在你的问题,什么时候用什么。(或者更确切地说是正确的问题版本。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.

最后读一本书,而不是仅仅依靠。

#7


5  

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.

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

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

二进制信号量=它更多的是一种信号机制,任何其他高优先级的线程都可以进行信号和锁定。

#8


2  

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

互斥对象是为了保护共享资源。信号量是分派线程。

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.

互斥:假设有一些票要卖。我们可以模拟这样一种情况:许多人同时购买机票:每个人都是一个购买机票的线程。显然,我们需要使用互斥锁来保护票据,因为它是共享资源。


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 b and a function getc() to do the calculation c = a + b.

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

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

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

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 t3 won't do its job untill t1 and t2 have done their jobs.

在信号量的帮助下,上面的代码可以确保t3不会在t1和t2完成工作之前完成它的工作。

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的特殊信号量。你也可以这样说,但是请注意它们在不同的情况下使用。即使你能做到这一点,也不要把一个取代另一个。

#9


1  

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.

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

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.

通过这种方式,生产者在填充队列时被阻塞,消费者在队列为空时被阻塞。

#10


1  

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.

互斥是信号量的一种特殊情况。信号量允许几个线程进入关键部分。在创建信号量时,定义如何在关键部分中允许线程。当然,您的代码必须能够处理对这个关键部分的几个访问。

#11


0  

All the above answers are of good quality,but this one's just to memorize.The name Mutex is derived from Mutually Exclusive hence you are motivated to think of a mutex lock as Mutual Exclusion between two as in only one at a time,and if I possessed it you can have it only after I release it.On the other hand such case doesn't exist for Semaphore is just like a traffic signal(which the word Semaphore also means).

以上的答案都是很好的,但是这个只是为了记住。互斥对象的名称源自互斥,因此您可以将互斥对象锁看作是两个互斥对象之间的互斥,就像一次只在一个互斥对象之间进行互斥一样。另一方面,这种情况并不存在,因为信号量就像一个交通信号(信号量这个词也有这个意思)。