0
votes

could anyone tell me how to use the mutex in the posix threads. we are decalaring a mutex as pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER.. and we are using pthread_mutex_lock(&mutex1) to lock the critical code. but my question is what does it lock we didnt specify which code to be locked if i have 4 threads and i want the thread 1 resources to be locked how could i tell that to the compiler and im unable to understand it can anyone help me guys. and whats the real use of mutex waiting for an answer ..

3

3 Answers

4
votes

It's entirely up to you to decide, pthreads doesn't specify what a lock does or does not protect.

E.g. if you want to protect a variable "a", it's up to you to ensure that all accesses to "a" happen under the protection of a mutex (say, "a_lock"). For a simple (untested) example


static int a;
static pthread_mutex_t a_lock = PTHREAD_MUTEX_INITIALIZER;

/* Add argument to static variable a in a thread-safe manner and return the result.  (In real life, for this kind of operation you could use an atomic operation) */
int increment_a(int i)
{
  int res;
  pthread_mutex_lock(&a_lock);
  a += i;
  res = a;
  pthread_mutex_unlock(&a_lock);
  return res;
}

That is, there is nothing in the hardware, OS, thread library, or anything else, that specifies any kind of relationship between the data you want to protect (variable "a" in the example above), and the mutex you're using to implement said protection (the mutex "a_lock" above). The pthread library only ensures that only one thread at a time may hold a mutex.

0
votes

The code it locks, protects, its the code between the lock and the unlock

pthread_mutex_lock(&mtx)
global_var = global_var + 10;
pthread_mutex_unlock(&mtx)

In this simple case you are protecting the increments of this global variable, this is necessary because the process of incrementing a number takes three steps:

  1. Reading the current value from ram
  2. Incrementing that value
  3. Writing that value back into ram

Let's focus on steps 1 and 2. A thread CAN (and will be, be sure of that) be switched just after step 1 (reading), and the other thread will read the same value as the first one, because it never got the opportunity to update back to ram. When the first thread resumes work (just after step 1), it will increment that value it read before and write back the wrong final value to ram, overwriting the second's thread work.

In other words:

[Thread 1] Reads the value 10
[Thread 2] Reads the value 10
[Thread 2] Increments it by 5 (value is now 15)
[Thread 2] Writes it back
[Thread 1] Increments it by 5 **(value is now 15)**
[Thread 1] Writes it back
Final value: 15

The final value should have been 20, not 15. See the problem? With a mutex you can serialize the access, putting stuff into proper order, so it becomes

[Thread 1] Reads the value 10
[Thread 1] Increments it by 5 (value is now 15)
[Thread 1] Writes it back
[Thread 2] Reads the value 15
[Thread 2] Increments it by 5 (value is now 20)
[Thread 2] Writes it back
Final value: 20

I'm sorry if I was confusing, but thread programming is confusing at first. Takes a while to think multithreaded, but linger there! It is a very important concept to grasp, especially now that multi-core CPUs are the de facto standard.

0
votes

Threads share memory (except the stack and possibly thread-local storage). So, you need to do something to avoid two threads stomping into each other.

Mutexes are a way to prevent threads from interfering into each other. A mutex is a MUTual EXClusion primitive, only one thread can hold a given mutex at a time.

So, if you want to protect some data structure from simultaneous access from several threads, you associate a mutex with that thread, and wrap every access to that data structure into mutex lock and unlock calls. This way, you ensure that only one thread can access the data structure at a time.

If a thread holds a mutex, and a second thread tries to lock the mutex, the second thread will block (sleep) until the first thread unlocks the mutex.