Mutexes
and Critical Regions
The simplest form of synchronization is a mutually exclusive (mutex) lock. Only one thread at a time
can acquire a mutex lock, so they can be placed around a data structure to
ensure that the data structure is modified by only one thread at a time.
Listing 4.7 shows how a mutex lock could be used to protect access to a
variable.
Listing 4.7 Placing
Mutex Locks Around Accesses to Variables
int
counter;
mutex_lock
mutex;
void
Increment()
{
acquire(
&mutex );
counter++;
release(
&mutex );
}
void
Decrement()
{
acquire(
&mutex );
counter--;
release(
&mutex );
}
In the example, the two routines Increment() and Decrement() will
either incre-ment or decrement the variable counter. To modify the variable, a
thread has to first acquire the mutex lock. Only one thread at a time can do
this; all the other threads that want to acquire the lock need to wait until
the thread holding the lock releases it. Both routines use the same mutex;
consequently, only one thread at a time can either incre-ment or decrement the
variable counter.
If multiple threads are attempting to acquire the
same mutex at the same time, then only one thread will succeed, and the other
threads will have to wait. This situation is known as a contended mutex.
The region of code between the acquisition and
release of a mutex lock is called a critical
section, or critical region. Code
in this region will be executed by only one thread at a time.
As an example of a critical section, imagine that
an operating system does not have an implementation of malloc() that is thread-safe, or safe
for multiple threads to call at the same time. One way to fix this is to place
the call to malloc() in a
critical section by surrounding it with a mutex lock, as shown in Listing 4.8.
Listing 4.8 Placing
a Mutex Lock Around a Region of Code
void
* threadSafeMalloc( size_t size )
{
acquire(
&mallocMutex );
void * memory = malloc( size );
release(
&mallocMutex );
return memory;
}
If all the calls to malloc() are
replaced with the threadSafeMalloc() call,
then only one thread at a time can be in the original malloc() code, and the calls to malloc() become
thread-safe.
Threads block if they attempt
to acquire a mutex lock that is already held by another thread. Blocking means
that the threads are sent to sleep either immediately or after a few
unsuccessful attempts to acquire the mutex.
One problem with this approach is that it can serialize a program. If multiple threads simultaneously call threadSafeMalloc(), only one thread at a time will make progress. This causes the
multithreaded program to have only a single executing thread, which stops the
program from taking advantage of multiple cores.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.