pthread_mutex_lock causes deadlock - c

I am using the above code to increment a counter using 2 threads, which independently take the mut lock and increment counter. I am facing a deadlock after the threads enter this function.
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
void *increment_counter(void *counter_addr)
{
int max = MAX_COUNTER_VALUE;
int iter;
int counter;
for(iter=0;iter< max ;iter++)
// LOCK
pthread_mutex_lock(&mut);
counter++;
// UNLOCK
pthread_mutex_unlock(&mut);
return NULL;
}
Could anyone please tell me where exactly am I going wrong?

You're trying to lock the mutex max times, then increment counter and release it once.
Try:
for(iter=0;iter< max ;iter++)
{
// LOCK
pthread_mutex_lock(&mut);
counter++;
// UNLOCK
pthread_mutex_unlock(&mut);
}
return NULL;

That is maybe what you tried to do:
int max = MAX_COUNTER_VALUE;
int iter;
int counter;
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
void *increment_counter(void *counter_addr)
{
pthread_mutex_lock(&mut);
for(iter=0;iter< max ;iter++)
counter++;
pthread_mutex_unlock(&mut);
return NULL;
}
2 or more threads share only global scope data or data located on the
heap(malloc).
2 or more threads do not share variables defined on the stack this
data is unique to each thread and there is no need to lock it.
You are welcomed to read in the answers what is shared and what is not shared etc.

As a principle, the same thread should not lock a mutex more than once and that's what happened here.

lock initialization is very important. If you don't initialize your locks to the right value your code breaks. One method for initializing your lock is the following:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
Also you can do this task dynamically by using the following code:
int rc = pthread_mutex_init(&lock, NULL);
assert(rc == 0); // always check success!
Beside lock initialization, you should check for the return code of pthread_mutex_lock to see if it fails or not as if it fails, multiple thread can enter the critical section. For this purpose, you can use a code similar to this which checks for the return code of pthread_mutex_lock:
// Use this to keep your code clean but check for failures
// Only use if exiting program is OK upon failure
void Pthread_mutex_lock(pthread_mutex_t *mutex) {
int rc = pthread_mutex_lock(mutex);
assert(rc == 0);
}

Related

How do I sync my two threads which each use a while loop for a shared resource?

I am trying to do this implementation but it's not working properly.
I have a global variable called counter which starts at 100 and I have two threads.
Both threads are decrementing the counter in a while loop that runs if counter is != 0.
However though the thread which does decrement the counter to 0 will stop running as expected. But the thread which does not decrement the counter continues running when it should stop.
How do I fix this?
Below is my code:
int counter = 0;
pthread_mutex_t counter_mutex;
void *Thread1(void *vargs)
{
while (counter != 0) {
pthread_mutex_lock(&counter_mutex);
counter--;
pthread_mutex_unlock(&counter_mutex);
}
sleep(1);
printf("Completed Thread1\n");
return NULL;
}
void *Thread2(void *vargs)
{
while (counter != 0) {
pthread_mutex_lock(&counter_mutex);
counter--;
pthread_mutex_unlock(&counter_mutex);
}
sleep(1);
printf("Completed Thread2\n");
return NULL;
}
int main(void)
{
pthread_t tid[2];
// initialize the mutex
pthread_mutex_init(&counter_mutex, NULL);
// create worker threads
pthread_create(&tid[0], NULL, Thread1, NULL);
pthread_create(&tid[1], NULL, Thread2, NULL);
// wait for worker threads to terminate
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
// print final counter value
printf("Counter is %d\n", counter);
return 0;
}
Output:
Completed Thread1
Thread1 completes but the program runs indefinitely because Thread2 stays in the while loop and doesn't finish.
Or vice versa, where Thread2 completes and then runs indefinitely because Thread1 stays
in the while loop and doesn't finish.
I'm really confused on how to approach fixing this problem because the two Threads should be running and stopping when counter == 0. However only the Thread that decrements counter to 0, stops while the other runs indefinitely.
Any and all help is really appreciated!
Thank you so much
At some point, while one thread will be blocked waiting to lock the mutex, the other will have decremented counter to zero. As soon as the waiting thread gains access to the lock, it will decrement as well, resulting in -1. counter will never approach zero again, and it will be decremented until Undefined Behavior is invoked by overflowing a signed integer.
None of this really matters, because the read of counter in each while loop predicate is not protected by the mutex
while (counter != 0)
which means you can have a read/write race condition.
Instead, structure your locks so they fully surround all reads & writes, and adjust your predicate to be independently checked.
#include <pthread.h>
#include <stdio.h>
int counter = 0;
pthread_mutex_t counter_mutex;
void *runner(void *arg) {
int *n = arg;
int done = 0;
while (!done) {
pthread_mutex_lock(&counter_mutex);
if (counter == 0)
done = 1;
else
counter--;
pthread_mutex_unlock(&counter_mutex);
}
printf("Completed Thread %d\n", *n);
return NULL;
}
int main(void)
{
pthread_t tid[2];
int args[2] = { 1, 2 };
pthread_mutex_init(&counter_mutex, NULL);
pthread_create(&tid[0], NULL, runner, &args[0]);
pthread_create(&tid[1], NULL, runner, &args[1]);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
printf("Counter is %d\n", counter);
return 0;
}
FYI: This is practically always a bad idea:
while (...trivial condition...) {
pthread_mutex_lock(&some_mutex);
...do some work...
pthread_mutex_unlock(&some_mutex);
}
The reason it's bad is that the loop tries to keep the mutex locked almost 100% of the time. The only time when the mutex is not locked is the brief moment when the loop evaluates the "...trivial condition..."
There's no point in executing the loop in more than one thread at the same time because the mutex prevents more than one thread from ever doing "...work..." at the same time.
If you're trying to use threads for parallel computing, then something like this works better:
typedef struct { ... } task_t;
int find_a_task(task_t* task) {
int result = FALSE;
pthread_mutex_lock(&some_mutex);
if (...there's more work to be done...) {
...copy from shared data into *task...
result = TRUE;
}
pthread_mutex_unlock(&some_mutex);
return result;
}
task_t local_task;
while (find_a_task(&local_task)) {
do_some_heavy_work_on(&local_task);
pthread_mutex_lock(&some_mutex);
if (...contents of local_task still are meaningful...) {
copy from local_task back to shared data structure
}
pthread_mutex_unlock(&some_mutex);
}
The idea is, to do most of the heavy work without keeping any mutex locked. The mutex is only briefly locked (a) before doing the heavy work, to copy shared data into private, local variables and (b) after the heavy work, to copy results, if still valid,* back into the shared data.
* The result might not still be valid because of some other thread changing shared data items that the caller used. This is optimistic locking. It may sound inefficient, but in many programs, the efficiency gained by not keeping a mutex locked while doing heavy work is MUCH greater than the efficiency lost because of threads occasionally duplicating or invalidating each other's effort.

Global variable not changing in thread?

I'm trying to update a global variable in the main function and have a thread tell me when this variable is positive.
The code: https://pastebin.com/r4DUHaUV
When I run it, only 2 shows up though 1 and 2 should be the correct answer.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_t tid;
pthread_mutex_t mtx;
pthread_cond_t cond;
int nr=0;
void* function(void* arg)
{
pthread_mutex_lock(&mtx);
printf("Number in thread : %d \n",nr);
while(nr<=0)
pthread_cond_wait(&cond,&mtx);
printf("Number %d is positive \n",nr);
pthread_mutex_unlock(&mtx);
}
int main()
{
pthread_mutex_init(&mtx,NULL);
pthread_create(&tid,NULL,function,NULL);
int i;
for(i=0;i<3;i++)
{
int isPos=0;
pthread_mutex_lock(&mtx);
if(i==0)
nr=nr+1;
if(i==1)
nr=nr-2;
if(i==2)
nr=nr+3;
if(nr>0)
isPos=1;
if(isPos==1)
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx);
}
pthread_join(tid,NULL);
return 0;
}
As I mentioned in general comment, I'll repeat here:
There is no guarantee the main thread won't go off, locking the mutex,
changing nr, signaling the cv (whether or not anyone is actually
waiting on it), and unlocking the mutex, all before the child thread
even locks the mutex, much less starts waiting on the cv. In that
case, nr can be 1 (or 2, etc) when the child finally gets the mutex.
That means your while loop will be skipped (nr<=0 is not true), and
whatever the current value of nr is will be printed on the way out.
I've run this several times, and gotten 1x1, 1x2, and 2x2, multiple
times.
A simple fix for this involves using the cv/mtx pair you've set up for monitoring for changes from main to also monitor startup-start from function. First the code:
The Code
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int nr = -1;
void* function(void* arg)
{
// signal main to start up once we start waiting
pthread_mutex_lock(&mtx);
nr = 0;
pthread_cond_signal(&cond);
// now start waiting (which will unlock the mutex as well, which means
// the main thread will be be able to acquire it and check nr safely
while(nr<=0)
pthread_cond_wait(&cond,&mtx);
printf("Number %d is positive \n",nr);
pthread_mutex_unlock(&mtx);
return NULL;
}
int main()
{
pthread_t tid;
pthread_create(&tid,NULL,function,NULL);
// wait until child is knowingly waiting
pthread_mutex_lock(&mtx);
while (nr != 0)
pthread_cond_wait(&cond, &mtx);
pthread_mutex_unlock(&mtx);
// now we know the child is ready to receive signals
int i;
for(i=0;i<3;i++)
{
pthread_mutex_lock(&mtx);
if(i==0)
nr=nr+1;
if(i==1)
nr=nr-2;
if(i==2)
nr=nr+3;
int isPos = (nr>0);
pthread_mutex_unlock(&mtx);
if (isPos)
pthread_cond_signal(&cond);
}
pthread_join(tid,NULL);
return 0;
}
How It Works
The initial value of nr is established as -1. Only the child thread will change this directly to 0, and even then only under the protection of the predicate mutex.
// signal main to start up once we start waiting
pthread_mutex_lock(&mtx);
nr = 0;
pthread_cond_signal(&cond);
Note that after the above three lines, the child still owns the mutex. It atomically releases it and begins waiting for notifications with the first entry into the subsequent loop:
while(nr<=0)
pthread_cond_wait(&cond,&mtx);
Now, back in main, the startup creates the child thread, acquires the mutex, then monitors until nr is zero.
pthread_create(&tid,NULL,function,NULL);
// wait until child is knowingly waiting
pthread_mutex_lock(&mtx);
while (nr != 0)
pthread_cond_wait(&cond, &mtx);
pthread_mutex_unlock(&mtx);
The only way to make it past this is when nr == 0. When that happens, the child must have changed it, but more importantly, it also must be waiting on the condition variable (that is how we got the mutex; remember?) From that point on, the code is similar. Worth noting, I use the pthread initializers to ensure the mutex and cvar are properly stood up. Your original post was missing the cvar initialization.
Lastly, doing multiple-predicate double-duty with a single cvar-mtx pair is easy to mess up, and can be very hard to detect edge cases when you did (mess up, that is). Be careful. This specific example is a hand-off sequence of duties, not concurrent duties, making it fairly trivial, so I'm comfortable in showing it.
Hope it helps.

unexpected behavior when using conditional variables (c, gcc)

I am trying to learn how to use conditional variables properly in C.
As an exercise for myself I am trying to make a small program with 2 threads that print "Ping" followed by "Pong" in an endless loop.
I have written a small program:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* T1(){
printf("thread 1 started\n");
while(1)
{
pthread_mutex_lock(&lock);
sleep(0.5);
printf("ping\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
pthread_cond_wait(&cond,&lock);
}
}
void* T2(){
printf("thread 2 started\n");
while(1)
{
pthread_cond_wait(&cond,&lock);
pthread_mutex_lock(&lock);
sleep(0.5);
printf("pong\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
int main(void)
{
int i = 1;
pthread_t t1;
pthread_t t2;
printf("main\n");
pthread_create(&t1,NULL,&T1,NULL);
pthread_create(&t2,NULL,&T2,NULL);
while(1){
sleep(1);
i++;
}
return EXIT_SUCCESS;
}
And when running this program the output I get is:
main
thread 1 started
thread 2 started
ping
Any idea what is the reason the program does not execute as expected?
Thanks in advance.
sleep takes an integer, not a floating point. Not sure what sleep(0) does on your system, but it might be one of your problems.
You need to hold the mutex while calling pthread_cond_wait.
Naked condition variables (that is condition variables that don't indicate that there is a condition to read somewhere else) are almost always wrong. A condition variable indicates that something we are waiting for might be ready to be consumed, they are not for signalling (not because it's illegal, but because it's pretty hard to get them right for pure signalling). So in general a condition will look like this:
/* consumer here */
pthread_mutex_lock(&something_mutex);
while (something == 0) {
pthread_cond_wait(&something_cond, &something_mutex);
}
consume(something);
pthread_mutex_unlock(&something_mutex);
/* ... */
/* producer here. */
pthread_mutex_lock(&something_mutex);
something = 4711;
pthread_cond_signal(&something_cond, &something_mutex);
pthread_mutex_unlock(&something_mutex);
It's a bad idea to sleep while holding locks.
T1 and T2 are not valid functions to use as functions to pthread_create they are supposed to take arguments. Do it right.
You are racing yourself in each thread between cond_signal and cond_wait, so it's not implausible that each thread might just signal itself all the time. (correctly holding the mutex in the calls to pthread_cond_wait may help here, or it may not, that's why I said that getting naked condition variables right is hard, because it is).
First of all you should never use sleep() to synchronize threads (use nanosleep() if you need to reduce output speed). You may need (it's a common use) a shared variable ready to let each thread know that he can print the message. Before you make a pthread_cond_wait() you must acquire the lock because the pthread_cond_wait() function shall block on a condition variable. It shall be called with mutex locked by the calling thread or undefined behavior results.
Steps are:
Acquire the lock
Use wait in a while with a shared variable in guard[*]
Do stuffs
Change the value of shared variable for synchronize (if you've one) and signal/broadcast that you finished to work
Release the lock
Steps 4 and 5 can be reversed.
[*]You use pthread_cond_wait() to release the mutex and block the thread on the condition variable and when using condition variables there is always a Boolean predicate involving shared variables associated with each condition wait that is true if the thread should proceed because spurious wakeups may occur. watch more here
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int ready = 0;
void* T1(){
printf("thread 1 started\n");
while(1)
{
pthread_mutex_lock(&lock);
while(ready == 1){
pthread_cond_wait(&cond,&lock);
}
printf("ping\n");
ready = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
void* T2(){
printf("thread 2 started\n");
while(1)
{
pthread_mutex_lock(&lock);
while(ready == 0){
pthread_cond_wait(&cond,&lock);
}
printf("pong\n");
ready = 0;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
int main(void)
{
int i = 1;
pthread_t t1;
pthread_t t2;
printf("main\n");
pthread_create(&t1,NULL,&T1,NULL);
pthread_create(&t2,NULL,&T2,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return EXIT_SUCCESS;
}
You should also use pthread_join() in main instead of a while(1)

Locking global array in a reentrancy-desired function in a multithreaded program?

Sorry if a question title is confusing. I just wanted to put all the things together.
I have a piece of code like:
int newThread(int(*pfunc)())
{
pthread_t tid;
pthread_create(&tid, NULL, pfunc, NULL);
int i = 0;
while(threads[i] != 0 && i < MAX_NUM_THREADS)
{
if ((MAX_NUM_THREADS - 1) == i)
{
puts("We've run out of threads' number limit\n");
return 1;
}
++i;
}
threads[i] = tid;
pthread_join(tid, NULL);
return 0;
}
threads[] is a global array. I want to make this function reentrant, but this means I shouldn't use global variables as far as I understand. I guess that's because values of global variables can be unpredictable at a certain time. But in my case the array seems to be quite predictable.
Is it ok, if I lock array with a mutex to make this function reentrant?
If yes, then how do I do it right? Just lock the first element before using it and unlock after? or is it better to lock/unlock every element while accessing it?
Is this even possible to make this function reentrant?
To say a function is reentrant, it should only rely on local variables to be simultaneously called by two (or more threads) and return correct results.
If the function rely on some shared data, (we can't really made it reentrant), we can make it thread-safe to be called simultaneously by two (or more) threads if all access to the shared data is serialized.
To make your function thread-safe, you should lock the loop and the insertion into threads[]. If you lock only the loop part, somebody could modify the content of threads between the end of the loop and the affectation at rank i.
pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
int newThread(int(*pfunc)())
{
pthread_t tid;
pthread_create(&tid, NULL, pfunc, NULL);
int i = 0;
pthread_mutex_lock(&mymutex); // take the lock
while(threads[i] != 0 && i < MAX_NUM_THREADS)
{
if ((MAX_NUM_THREADS - 1) == i)
{
puts("We've run out of threads' number limit\n");
pthread_mutex_unlock(&mymutex); // don't forget to release the lock here too :)
return 1;
}
++i;
}
threads[i] = tid;
pthread_mutex_unlock(&mymutex); // release the lock
pthread_join(tid, NULL);
return 0;
}

Check to see if a pthread mutex is locked or unlocked (After a thread has locked itself)

I need to see if a mutex is locked or unlocked in an if statement so I check it like this...
if(mutex[id] != 2){
/* do stuff */
}
but when I check it gcc gives me the following error:
error: invalid operands to binary != (have 'ptherad_mutex_t' and 'int')
So how can I check to see if the mutex is locked or not?
EDIT:
A key component to my problem is that my threads (by design) lock themselves right AFTER passing control to another thread. So when thread A passes control to thread B thread A is locked, thread B does some stuff, then when thread B is done it will unlock thread A.
The problem with this is that if thread B attempts to unlock thread A and thread A has not yet completed locking itself then the call to unlock is lost and thread A remains locked which causes a dead lock.
UPDATE:
I remade my program taking caf's suggestion but I am still running into problems. I have molded my program into the structure caf provided the best I can but I cannot even tell what is causing the dead lock now... I have created a new question here seeking help with my code.
Below is a runnable version of caf's suggestion. I made a small reordering in the function for thread a, without which both thread a and thread b would have been locked upon their creation, waiting for a condition that could never change.
#include <pthread.h>
int run_a = 0;
pthread_mutex_t lock_a = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_a = PTHREAD_COND_INITIALIZER;
int run_b = 0;
pthread_mutex_t lock_b = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_b = PTHREAD_COND_INITIALIZER;
void *a(void *);
void *b(void *);
int main(){
int status;
pthread_t thread_a;
pthread_t thread_b;
pthread_create(&thread_a, NULL, a, (void *)0);
pthread_create(&thread_b, NULL, b, (void *)0);
pthread_join(thread_a, (void **)&status);
pthread_join(thread_b, (void **)&status);
}
/* thread A */
void *a(void *i){
while (1) {
printf("thread A is running\n");
sleep(1);
/* unlock thread B */
pthread_mutex_lock(&lock_b);
run_b = 1;
pthread_cond_signal(&cond_b);
pthread_mutex_unlock(&lock_b);
/* wait for thread A to be runnable */
pthread_mutex_lock(&lock_a);
while (!run_a)
pthread_cond_wait(&cond_a, &lock_a);
run_a = 0;
pthread_mutex_unlock(&lock_a);
}
}
/* thread B */
void *b(void *i){
while (1) {
/* wait for thread B to be runnable */
pthread_mutex_lock(&lock_b);
while (!run_b)
pthread_cond_wait(&cond_b, &lock_b);
run_b = 0;
pthread_mutex_unlock(&lock_b);
printf("thread B is running\n");
sleep(1);
/* unlock thread A */
pthread_mutex_lock(&lock_a);
run_a = 1;
pthread_cond_signal(&cond_a);
pthread_mutex_unlock(&lock_a);
}
}
You can use pthread_mutex_trylock. If that succeeds, the mutex was unclaimed and you now own it (so you should release it and return "unheld", in your case). Otherwise, someone is holding it.
I have to stress though that "check to see if a mutex is unclaimed" is a very bad idea. There are inherent race conditions in this kind of thinking. If such a function tells you at time t that the lock is unheld, that says absolutely nothing about whether or not some other thread acquired the lock at t+1.
In case this is better illustrated with a code example, consider:
bool held = is_lock_held();
if (!held)
{
// What exactly can you conclude here? Pretty much nothing.
// It was unheld at some point in the past but it might be held
// by the time you got to this point, or by the time you do your
// next instruction...
}
Mutexes are not the right primitive for the scheme that you want to implement. You should be using condition variables:
int run_thread_a = 0;
pthread_mutex_t run_lock_a = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t run_cond_a = PTHREAD_COND_INITIALIZER;
int run_thread_b = 0;
pthread_mutex_t run_lock_b = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t run_cond_b = PTHREAD_COND_INITIALIZER;
/* thread A */
while (1) {
/* Wait for Thread A to be runnable */
pthread_mutex_lock(&run_lock_a);
while (!run_thread_a)
pthread_cond_wait(&run_cond_a, &run_lock_a);
run_thread_a = 0;
pthread_mutex_unlock(&run_lock_a);
/* Do some work */
/* Now wake thread B */
pthread_mutex_lock(&run_lock_b);
run_thread_b = 1;
pthread_cond_signal(&run_cond_b);
pthread_mutex_unlock(&run_lock_b);
}
/* thread B */
while (1) {
/* Wait for Thread B to be runnable */
pthread_mutex_lock(&run_lock_b);
while (!run_thread_b)
pthread_cond_wait(&run_cond_b, &run_lock_b);
run_thread_b = 0;
pthread_mutex_unlock(&run_lock_b);
/* Do some work */
/* Now wake thread A */
pthread_mutex_lock(&run_lock_a);
run_thread_a = 1;
pthread_cond_signal(&run_cond_a);
pthread_mutex_unlock(&run_lock_a);
}
Each thread will block in pthread_cond_wait() until the other thread signals it to wake up. This will not deadlock.
It can easily be extended to many threads, by allocating one int, pthread_cond_t and pthread_mutex_t per thread.
You can't compare a pthread_mutex_t with a int.
You can use
int pthread_mutex_trylock(pthread_mutex_t *mutex);
to check that.

Resources