- Back to Home »
- Threading - FAQ
Posted by : Sushanth
Tuesday, 15 December 2015
FAQ:
1. Is it possible to use mutex in multiprocessing case on unix?
Mutual exclusion locks
(mutexes) prevent multiple
threads from simultaneously
executing critical sections of code that access shared data (that is, mutexes
are used to serialize
the execution of
threads). All mutexes must be
global. A successful call for a mutex
lock by
way of mutex_lock()
will cause another
thread that is also trying to lock the
same mutex to block until the owner thread unlocks it by way of
mutex_unlock(). Threads within
the same process or
within other processes can share mutexes.
Mutexes can synchronize threads within the
**same process** or
in ***other processes***. Mutexes
can be used to synchronize threads between processes if the mutexes are
allocated in writable
memory and shared among the
cooperating processes and have been initialized for this task. Initialize
Mutexes are either intra-process or inter-process, depending upon the argument
passed implicitly or explicitly to the initialization of that mutex. A
statically allocated mutex does not need to be explicitly initialized; by
default, a statically allocated mutex is initialized with all zeros and its
scope is set to be within the calling process. For inter-process synchronization,
a mutex needs to be allocated in memory shared between these processes. Since the
memory for such a mutex must be allocated dynamically, the mutex needs to be explicitly initialized
using mutex_init().
PTHREAD_PROCESS_SHARED The mutex can synchronize threads in this process and other processes.
2. Is it a good practice to lock a mutex from the main thread, and release from another thread?
A mutex can only be unlocked by the same thread that
locked it. A program that violates this rule has undefined behavior and
is not portable or stable; it may seem to work at times and fail horribly at
other times, when compiled on a slightly different system, during a different
phase of the moon, or after you upgrade.If you really need this sort of
behavior (locking by one thread and unlocking by another), a semaphore may meet
your needs. Semaphores do not have owners, and any thread may call sem_post or
sem_wait at basically any time.
While they can sometimes be used interchangeably,
mutexes and semaphores have very different conceptual foundations. The degree
to which their actual behavior differs depends on your particular application.
A mutex conceptually has an owner - one thread
which, by convention/contract, the programmer treats as the only thread allowed
to access the resource(s) which the mutex protects. Depending on the type of
mutex it is and the implementation, the owner may be purely a formal construct,
or may be an actual field stored in the mutex object. For recursive or
error-checking mutexes, for example, storing an owner allows the thread that
owns the mutex to obtain additional reference counts on it, or to obtain an
error if it tries to re-lock it while the lock is still held, respectively.
A semaphore, on the other hand, is fundamentally a
counter. Waiting on a semaphore is not necessarily tied to obtaining exclusive
rights to using a resource, although of course that's one potential application
(a semaphore which only takes on the values 0 and 1 can be used as a mutex).
Semaphores can be used for many other applications, like waiting/signaling -
for example, one thread could loop waiting on a semaphore N times to wait for N
threads to post to it, where each thread posts when it finishes a task. In
fact, a synchronization object equivalent to condition variables can also be
implemented in terms of semaphores. They can also be used simply as a portable
atomic counter (posting to increment the counter), among many other uses. The
"classic" use of a semaphore is to represent the number of available
resources from among N equivalent resources, and facilitate waiting when no
resources are available, but personally I don't think I've ever used semaphores
quite like that.
Now if you want to get into the specifics of POSIX
mutexes and semaphores, for the most part semaphores are much more powerful.
Not only can they be used for signalling conditions; the post operation is also
async-signal-safe meaning you can use it without restriction from inside
signal handlers. On the other hand, mutexes do have one feature which cannot be
implemented in terms of semaphores: the robust mutex attribute, which
allows you to create mutexes that allow other threads/processes to detect and
recover when a thread/process terminated while holding the mutex (rather than
just deadlocking).
3.What are critical sections in threads
In normal use, a critical section is
a section of code that must be executed serially -- i.e., only one thread can
execute that code at any given time. You normally accomplish that by protecting
the code with a mutex semaphore.
In Windows parlance, a critical
section is a data structure (and a few associated functions) that implement at
process-specific mutex semaphore (i.e., one that's used only for locking
between threads in a single process, not between separate processes).
There are two varieties of
semaphores. A mutex semaphore lets only one thread execute at a time. A counted
semaphore lets you specify the maximum number of threads that can execute
simultaneously. Mutex semaphores are the more common variety, but counted
semaphores definitely have uses as well.
4.How to check whether pthread_mutex is locked or not
The following is an outline of one of the
methods
void Method1()
{
try
{
pthread_mutex_lock(&syncLock);
statement1;
statement2;
pthread_mutex_unlock(&syncLock);
statement3;
statement4;
}
catch(exception& e)
{
log error
}
}
where syncLock is of type pthread_mutex_t and is
initialized using the default initialization.
My question is that if an exception is thrown in the
statement2 of the method then the control passes directly to the catch
statement. In that case my mutex remains locked. But I also cant simply write
an unlock statement in the catch block since if the exception came from
statement 3 then the mutex has been unlocked and calling unlock on an already
unlocked mutex results in undefined behavior.
So is there a way I can check whether the mutex has
been unlocked or not in the catch statement. Or, is there a C# style lock
statement alternative available in c++ so I am sure that the lock is released
even if an exception is thrown from within that block
Solution:
Write a tiny RAII-style locker class:
class lock {
pthread_mutex_t &mutex;
public:
lock(pthread_mutex_t &m) :mutex(m) { pthread_mutex_lock(&mutex);
}
~lock() { pthread_mutex_unlock(&mutex); }
};
Then write your code something like this:
void Method1()
{
try
{
{
lock l(syncLock);
statement1;
statement2;
}
statement3;
statement4;
}
catch(exception& e)
{
log error
}
}
When you exit from the scope where you defined the
lock, the lock will be destroyed via the destructor, thus calling
pthread_mutex_unlock. That happens whether you exit the scope normally or via
an exception. When you enter the exception handler, you know the mutex has been
unlocked.
5. Problem:You are given a paragraph
, which contain n number of words, you are given m threads. What you need to do
is , each thread should print one word and give the control to next thread,
this way each thread will keep on printing one word , in case last thread come,
it should invoke the first thread. Printing will repeat until all the words are
printed in paragraph. Finally all threads should exit gracefully. What kind of
synchronization will use?
Solution: Semaphores are used to signal
another thread that it's their turn. They are used much less frequently than
mutexes, which I guess is why they think it's a good interview question. It's
also why the example seems contrived.
Basically,
you would create m semaphores. Each thread x waits on semaphore x then posts to
semaphore x+1 after doing its thing. In pseudocode:
loop:
wait(semaphore[x])
if no more words:
post(semaphore[(x+1) % m])
exit
print word
increment current word pointer
post(semaphore[(x+1) % m])
6.What happens to other threads when one thread forks?
In C++ using pthreads,
what happens to your other threads if one of your threads calls fork?
Nothing. Only the thread
calling fork() gets duplicate. The child process has to start any new threads.
The parents threads are left alone.