82

What is the difference between semaphores and mutex provided by pthread library ?

Sagar Jain
  • 7,475
  • 12
  • 47
  • 83
cppdev
  • 6,833
  • 13
  • 40
  • 45
  • 11
    Semaphores aren't provided by pthreads, and can be used in non-threaded programs as well. – ephemient Jan 14 '10 at 18:51
  • 5
    any synchronization construct can be used in non-threaded code :P – Hassan Syed Jan 14 '10 at 19:15
  • 4
    Well, the difference I intended to highlight is that semaphores were in use prior to pthreads. You can place a `sem_t` in shared memory and use it to synchronize operations between processes. On the other hand, even if you don't create multiple threads, you must compile&link with `-pthread` in order to use `pthread_mutex_*`. (Some platforms don't enforce this, but that's the standard.) – ephemient Jan 14 '10 at 20:51
  • 2
    @ephemient, actually `man sem_init` in Linux says: `Link with -pthread.` So I guess in that Linux does not follow POSIX to the letter. – Alexis Wilke May 28 '14 at 02:07

9 Answers9

88

semaphores have a synchronized counter and mutex's are just binary (true / false).

A semaphore is often used as a definitive mechanism for answering how many elements of a resource are in use -- e.g., an object that represents n worker threads might use a semaphore to count how many worker threads are available.

Truth is you can represent a semaphore by an INT that is synchronized by a mutex.

Hassan Syed
  • 20,075
  • 11
  • 87
  • 171
  • 3
    setting the counter to 1 (whatever value that represents) the semaphore becomes a mutex – stacker Jan 14 '10 at 16:44
  • 1
    Does it mean that mutex and binary semaphores are one & the same – cppdev Jan 14 '10 at 16:48
  • 6
    No see http://www.opengroup.org/onlinepubs/009695399/functions/sem_wait.html and http://www.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_lock.html. – Richard Pennington Jan 14 '10 at 16:51
  • 171
    One significant difference (since I've seen people make this mistake before): a semaphore may be procured and vacated by any thread in any sequence (so long as the count is never negative), but a mutex may **only** be unlocked by the thread that locked it. Attempting to unlock a mutex which was locked by another thread is undefined behavior. – ephemient Jan 14 '10 at 18:50
  • 5
    @ephemient, that would have made a great answer, very insightful – Matt Joiner Jan 15 '10 at 09:06
  • 11
    @ephemient: for the reason that you specify, the last assertion in the answer is false: you CANNOT represent a semaphore by an INT that is synchronized by a mutex since, if the mutex is held, you cannot increment/decrement the int from another thread, and you'll have to wait for the locking thread to release the mutex. The cornerstone difference is that the mutex is owned, while the semaphore is not owned. And that ownership, through the imposed synchronisation, is transmitted to the INT. So, you obtain some hybrid, owned semaphore, somewhere between the unowned semaphore and the owned mutex. – user1284631 Feb 12 '13 at 11:15
  • 25
    I think this answer still misses one VERY crucial distinction between a semaphore and a mutex; that is the usage. Semaphores are signaling mechanisms at their heart; the fact that they can be incremented and decremented by any thread is just a result of this. Semaphores are used to signal to other flows-of-control something related to synchronization (like a fully/empty buffer). A mutex on the other hand, is always used to protect multiple access to a shared object. That's a big difference and people somehow always seem to miss it, or I never understand what they're trying to say. :P – Fingolfin Jun 11 '13 at 20:45
  • 1
    Downvoted. The statement "truth is you can represent a semaphore by an INT that is synchronized by a mutex" is wrong. If you choose to implement it that way, you would need a condition variable too, to keep track of the threads waiting on the semaphore. – Călin Nov 26 '20 at 17:45
19

I am going to talk about Mutex vs Binary-Semaphore. You obviously use mutex to prevent data in one thread from being accessed by another thread at the same time.

(Assume that you have just called lock() and in the process of accessing a data. This means that, you don’t expect any other thread (or another instance of the same thread-code) to access the same data locked by the same mutex. That is, if it is the same thread-code getting executed on a different thread instance, hits the lock, then the lock() should block the control flow.)

This applies to a thread that uses a different thread-code, which is also accessing the same data and which is also locked by the same mutex.

In this case, you are still in the process of accessing the data and you may take, say, another 15 secs to reach the mutex unlock (so that the other thread that is getting blocked in mutex lock would unblock and would allow the control to access the data).

Do you ever allow another thread to just unlock the same mutex, and in turn, allow the thread that is already waiting (blocking) in the mutex lock to unblock and access the data? (Hope you got what I am saying here.)

As per agreed-upon universal definition,

  • with “mutex” this can’t happen. No other thread can unlock the lock in your thread
  • with “binary-semaphore” this can happen. Any other thread can unlock the lock in your thread

So, if you are very particular about using binary-semaphore instead of mutex, then you should be very careful in “scoping” the locks and unlocks, I mean, that every control-flow that hits every lock should hit an unlock call and also there shouldn’t be any “first unlock”, rather it should be always “first lock”.

rajah9
  • 11,645
  • 5
  • 44
  • 57
Paxi
  • 191
  • 1
  • 2
  • I like the **scoping** part. It refers to the implementation part that differs in binary semaphore and mutex. – KRoy May 17 '16 at 18:06
15

The Toilet Example

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.

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

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

Semaphore:

Is the number of free identical toilet keys. For 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.

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

Source

Ankur
  • 1,385
  • 11
  • 21
8

mutex is used to avoid race condition between multiple threads.

whereas semaphore is used as synchronizing element used across multiple process.

mutex can't be replaced with binary semaphore since, one process waits for semaphore while other process releases semaphore. In case mutex both acquisition and release is handled by same.

zed_0xff
  • 32,417
  • 7
  • 53
  • 72
C Learner
  • 2,287
  • 2
  • 14
  • 7
  • 1
    (-1) Incorrect generalization: for one, mutex's can be shared across processes -- for example: http://msdn.microsoft.com/en-us/library/ms682411(VS.85).aspx. If your system doesn't have named mutex's just map some shared memory and create your own. – Hassan Syed Jan 17 '10 at 15:53
  • 1
    Not fair to flag it as "not useful". I have worked on M$ quite a bit. It is easy to tell someone to use shared memory. on M$, all kernel objects are named and shared. Mutex is a kernel object. A pthread mutex is a CRITICAL_SECTION in M$. There is no way to share CRITICAL_SECTION between processes! – deepsnore Jun 22 '10 at 11:20
  • @hackworks - pthread_mutex can be initialized with "_POSIX_THREAD_PROCESS_SHARED" flag which allows it to work in interprocess environment: http://linux.die.net/man/3/pthread_mutexattr_init – killdaclick Dec 02 '13 at 09:39
4

This two articles explain great details about mutex vs semaphores Also this stack overflow answer tells the similar answer.

Community
  • 1
  • 1
tsenapathy
  • 5,646
  • 3
  • 26
  • 26
4

The difference between the semaphore and mutex is the difference between mechanism and pattern. The difference is in their purpose (intent)and how they work(behavioral).

The mutex, barrier, pipeline are parallel programming patterns. Mutex is used(intended) to protect a critical section and ensure mutual exclusion. Barrier makes the agents(thread/process) keep waiting for each other.

One of the feature(behavior) of mutex pattern is that only allowed agent(s)(process or thread) can enter a critical section and only that agent(s) can voluntarily get out of that.

There are cases when mutex allows single agent at a time. There are cases where it allows multiple agents(multiple readers) and disallow some other agents(writers).

The semaphore is a mechanism that can be used(intended) to implement different patterns. It is(behavior) generally a flag(possibly protected by mutual exclusion). (One interesting fact is even mutex pattern can be used to implement semaphore).

In popular culture, semaphores are mechanisms provided by kernels, and mutexes are provided by user-space library.

Note, there are misconceptions about semaphores and mutexes. It says that semaphores are used for synchronization. And mutexes has ownership. This is due to popular OS books. But the truth is all the mutexes, semaphores and barriers are used for synchronization. The intent of mutex is not ownership but mutual exclusion. This misconception gave the rise of popular interview question asking the difference of the mutexes and binary-semaphores.

Summary,

intent
  • mutex, mutual exclusion
  • semaphore, implement parallel design patterns
behavior
  • mutex, only the allowed agent(s) enters critical section and only it(they) can exit
  • semaphore, enter if the flag says go, otherwise wait until someone changes the flag

In design perspective, mutex is more like state-pattern where the algorithm that is selected by the state can change the state. The binary-semaphore is more like strategy-pattern where the external algorithm can change the state and eventually the algorithm/strategy selected to run.

KRoy
  • 1,290
  • 14
  • 10
2

Semaphore is more used as flag, for which your really don't need to bring RTOS / OS. Semaphore can be accidentally or deliberately changed by other threads (say due to bad coding). When you thread use mutex, it owns the resources. No other thread can ever access it, before resource get free.

ajinkya
  • 21
  • 1
-1

Mutexes can be applied only to threads in a single process and do not work between processes as do semaphores.

batteringRam
  • 75
  • 2
  • 5
  • This is incorrect, see https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setpshared.html. – rtx13 May 07 '20 at 15:23
-1

Mutex is like sempaphore with with S=1.

You can control number of concurrent accesses with semaphore but with mutex only one process at a time can access it.

See the implemenation of these two below: (all functions are atomic)

Semaphore:

wait(S) {
      while (S <= 0 )
         ; // busy wait
      S--;
}

signal(S) {
      S++;
}

Mutex:

acquire() {
      while (!available)
            ; // busy wait
      available = false;
}

release() {
      available = true;
}
Ava
  • 41
  • 8