I was thinking to improve my
threading fundamentals, so I planned to make few notes for myself that will
assist me in future (Obviously at the time of Interviews). Following questions
and answers have been taken from stackoverflow.com. This post is a sticky notes
post for me.
Let’s understand it from Sun’s
point of view.
A counting semaphore.
Conceptually, a semaphore maintains a set of permits. Each acquire() blocks
if necessary until a permit is available, and then takes it. Each release() adds
a permit, potentially releasing a blocking acquirer. However, no actual permit
objects are used; the Semaphore just keeps a count of the number
available and acts accordingly.
Semaphores are often used to
restrict the number of threads than can access some (physical or logical)
resource.
Before obtaining an item each thread must
acquire a permit from the semaphore, guaranteeing that an item is available for
use. When the thread has finished with the item it is returned back to the pool
and a permit is returned to the semaphore, allowing another thread to acquire
that item. Note that no synchronization lock is held when acquire() is
called as that would prevent an item from being returned to the pool. The
semaphore encapsulates the synchronization needed to restrict access to the
pool, separately from any synchronization needed to maintain the consistency of
the pool itself.
A lock is a tool for controlling
access to a shared resource by multiple threads. Commonly, a lock provides
exclusive access to a shared resource: only one thread at a time can acquire
the lock and all access to the shared resource requires that the lock be
acquired first. However, some locks may allow concurrent access to a shared
resource, such as the read lock of a ReadWriteLock.
The use of synchronized methods
or statements provides access to the implicit monitor lock associated with
every object, but forces all lock acquisition and release to occur in a
block-structured way: when multiple locks are acquired they must be released in
the opposite order, and all locks must be released in the same lexical scope in
which they were acquired.
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 serialize 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."
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 serialize 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."
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 i.e 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.
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 i.e 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.
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)."
A mutex is locking
mechanism used to synchronize access to a resource. Only one task (can
be a thread or process based on OS abstraction) can acquire the mutex. It means
there will be ownership associated with mutex, and only the owner can release
the lock (mutex).
Semaphore is signaling
mechanism (“I am done, you can carry on” kind of signal). For example,
if you are listening songs (assume it as one task) on your mobile and at the
same time your friend called you, an interrupt will be triggered upon
which an interrupt service routine (ISR) will signal the call processing task
to wakeup.
Difference between Mutex and Semaphore
A thread running which accepts
client connections. This thread can handle 10 clients simultaneously. Then each
new client sets the semaphore until it reaches 10. When the Semaphore has 10
flags, then your thread won't accept new connections
Mutex are usually used for
guarding stuff. Suppose your 10 clients can access multiple parts of the
system. Then you can protect a part of the system with a mutex so when 1 client
is connected to that sub-system, no one else should have access.
Semaphores have no notion of
ownership, this means that any thread can release a semaphore (this can lead to
many problems in itself but can help with "death detection").
Whereas a mutex does have the
concept of ownership (i.e. you can only release a mutex you have acquired).
Binary Semaphore is a specialized
form of Semaphore where count is 1, so most of the developer thinks that these
two concepts can be implemented in the similar manner. But there are few
differences between Mutex and Binary Semaphore, it is better to say that we
will try to figure out the problems with binary Semaphore.
The problem with the semaphore is
that any thread can increment it or decrement it. In particular, if the
semaphore’s value is 0 (“locked”), another thread can increment it (“unlock”),
even if this is not the thread which locked it!
Another problem is that most
semaphore implementations allow sharing semaphores between processes.
It is the priority inversion
– a semaphore locked by a low priority process can block the whole OS if the
higher priority processes need to wait for unlocking/releasing the semaphore.
This condition happens though only for OS that uses fixed priority preemptive
scheduling – most RTOS for embedded devices are prone.
For further reading
No comments:
Post a Comment