Why does pthread_cond_signal not work? - c

I am currently learing all around POSIX threads (pthread).
I now have created a simple program which increased a shared value by 7 until above 10000 then it should signal a condition to the next thread which decreases it by 3 until under 1000. At last it should divide the result through 2 and main should output the result.
My code:
pthread_t threads[3];
pthread_cond_t cond_a, cond_b;
pthread_mutex_t mutex;
int counter;
void * worker_one();
void * worker_two();
void * worker_three();
int main(int argv, const char ** argc) {
counter = 0;
pthread_cond_init(&cond_a, NULL);
pthread_cond_init(&cond_b, NULL);
pthread_mutex_init(&mutex, NULL);
pthread_create(&threads[0], NULL, worker_one, NULL);
pthread_create(&threads[1], NULL, worker_two, NULL);
pthread_create(&threads[2], NULL, worker_three, NULL);
pthread_join(threads[0], NULL);
pthread_join(threads[1], NULL);
pthread_join(threads[2], NULL);
printf("Value started at %d and ends with %d.\n", 0, counter);
return 0;
}
void * worker_one() {
printf("Worker one started.\n");
pthread_mutex_lock(&mutex);
printf("Worker one starting work.\n");
while (counter < 10000) {
counter += 7;
}
pthread_cond_signal(&cond_a);
printf("Worker one finished work with: %d.\n", counter);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void * worker_two() {
printf("Worker two started.\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond_a, &mutex);
printf("Worker two starting work.\n");
while (counter > 1000)
counter -= 3;
printf("Worker two finished work with: %d.\n", counter);
pthread_cond_signal(&cond_b);
pthread_mutex_unlock(&mutex);
sleep(1);
pthread_exit(NULL);
}
void * worker_three() {
printf("Worker three started.\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond_b, &mutex);
printf("Worker three starting work.\n");
counter /= 2;
printf("Worker three finished work with: %d.\n", counter);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
For some reason the whole execution hangs around the first thread. The signal is also fired but thread two does not react.
Can somebody tell me what I am doing wrong?

I have answered a similar question here: pthread condition variables on Linux, odd behaviour.
The problem is that you wait before even testing the condition you want to wait for is true.
What happens is that thread 1 signals before thread 2 is waiting, therefore the signal is lost and thread 2 will be waiting forever.
In order to avoid this, first test what you want to wait for, then wait only if it's not here.
EDIT: Ok, here is a possible solution with only one mutex and one condtion (untested)
Thread 1:
pthread_mutex_lock(&mutex);
while(thread_1_should_work == false){ // wait until the condition is satisfied
pthread_cond_wait(&cond, &mutex);
}
//at this point, we owe the mutex and we know thread_1_should_work is true;
// do work
thread_1_shoudl_work = false;
thread_2_should_work = true;
pthread_cond_broadcast(&cond); //wake up any waiting thread (if it's not their turn, they'll call wait again)
pthread_mutex_unlock(&mutex);
... and so on.

Related

How to create 2 threads first one take input numbers and the second one collect them?

Here is my code. The sum part is not working. I need some controls for that but I couldn't do it.
I tried make number variable number=-1, but that also didn't work and I had an infinite loop.
By the way this is my first question that i ask here, so i can make mistakes. Sorry for that.
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdbool.h>
int number = 0, sum = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *threadFunction1()
{
pthread_mutex_lock(&mutex);
while (true)
{
printf("Number:");
scanf("%d", &number);
if (number == 0) break;
}
pthread_exit(NULL);
}
void *threadFunction2()
{
pthread_mutex_lock(&mutex);
while (true)
{
sum += number;
printf("Sum is:%d\n", sum);
if (number == 0) break;
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main()
{
pthread_t thread1, thread2;
int case1, case2;
case1 = pthread_create(&thread1, NULL, threadFunction1, NULL);
case2 = pthread_create(&thread2, NULL, threadFunction2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("It's over..\n");
pthread_mutex_destroy(&mutex);
return 0;
}
Here is the output
An immediately obvious issue is that threadFunction1 locks the mutex
pthread_mutex_lock(&mutex);
while (true)
{
printf("Number:");
scanf("%d", &number);
if (number == 0) break;
}
pthread_exit(NULL);
but never unlocks it. It is impossible to share a resource when one thread takes complete control over it.
The next issue is that the locking and unlocking of the mutex occurs outside of the while loop.
pthread_mutex_lock(&mutex);
while (true)
{
sum += number;
printf("Sum is:%d\n", sum);
if (number == 0) break;
}
pthread_mutex_unlock(&mutex);
This means whichever thread gets CPU time first will lock the mutex, and enter a potentially long running loop, only unlocking the mutex when that loop ends:
If threadFunction1 is the first to lock the mutex, this loop lasts until the user enters 0, wherein the loop is broken and the thread is terminated. After this, threadFunction2 never gets a turn, due to the lack of an unlock.
If threadFunction2 is the first to lock the mutex, this loop is broken after during its first iteration, as number is initialized to 0. After this the thread is terminated, and threadFunction1 would get a turn, since the mutex is unlocked.
The final issue is that a single mutex alone is not the correct tool to use here.
Even moving the locks and unlocks inside the loop, so that each thread has a chance to lock the mutex, do some work, and then unlock, there is no guarantee that both threads will get equal access to the lock.
while (true)
{
pthread_mutex_lock(&mutex);
sum += number;
printf("Sum is:%d\n", sum);
pthread_mutex_unlock(&mutex);
if (number == 0) break;
}
In fact, the opposite will probably occur. By default, it is very likely for one thread to be granted some CPU time, lock the mutex, do some work, unlock the mutex, and with its remaining time immediately lock the mutex again.
So we need a way to make two threads evenly share a resource.
One way is, instead of using a mutex, to use two semaphores to create a lockstep. This means one thread waits to for a semaphore which the other thread posts, and vice versa.
Note that in main we start the to_read semaphore with a value of 1, meaning the scanning thread effectively "goes first".
#include <pthread.h>
#include <semaphore.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
static int number = 0;
static int sum = 0;
static sem_t to_read;
static sem_t to_write;
static void *scanning(void *arg) {
while (true) {
sem_wait(&to_read);
printf("Enter a number: ");
if (1 != scanf("%d", &number))
number = 0;
sem_post(&to_write);
if (number == 0)
break;
}
return NULL;
}
static void *adding(void *arg) {
while (true) {
sem_wait(&to_write);
sum += number;
printf("Sum is: %d\n", sum);
sem_post(&to_read);
if (number == 0)
break;
}
return NULL;
}
int main(void) {
pthread_t thread1, thread2;
sem_init(&to_read, 0, 1);
sem_init(&to_write, 0, 0);
pthread_create(&thread1, NULL, scanning, NULL);
pthread_create(&thread2, NULL, adding, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
puts("It's over...");
sem_destroy(&to_read);
sem_destroy(&to_write);
}
Note that this will surely perform worse than a single threaded loop in main, doing the same amount of work, due to the overhead of context switching. That said, it is just a toy example.

Why some threads don't receive pthread_cond_broadcast?

I have a threadpool of workers. Each worker executes this routine:
void* worker(void* args){
...
pthread_mutex_lock(&mtx);
while (queue == NULL && stop == 0){
pthread_cond_wait(&cond, &mtx);
}
el = pop(queue);
pthread_mutex_unlock(&mtx);
...
}
main thread:
int main(){
...
while (stop == 0){
...
pthread_mutex_lock(&mtx);
insert(queue, el);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx);
...
}
...
}
Then I have a signal handler that executes this code when it receives a signal:
void exit_handler(){
stop = 1;
pthread_mutex_lock(&mtx);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mtx);
}
I have omitted declarations and initialization, but the original code has them.
After a signal is received most of the time it's all ok, but sometimes it seems that some worker threads stay in the wait loop because they don't see that the variable stop is changed and/or they are not waken up by the broadcast.
So the threads never end.
What I am missing?
EDIT: stop=1 moved inside the critical section in exit_handler. The issue remains.
EDIT2: I was executing the program on a VM with Ubuntu. Since the code appears to be totally right I tried to change VM and OS (XUbuntu) and now it seems to work correctly. Still don't know why, anyone has an idea?
Some guessing here, but it's too long for a comment, so if this is wrong, I will delete. I think you may have a misconception about how pthread_cond_broadcast works (at least something I've been burned with in the past). From the man page:
The pthread_cond_broadcast() function shall unblock all threads
currently blocked on the specified condition variable cond.
Ok, that make sense, _broadcast awakens all threads currently blocked on cond. However, only one of the awakened threads will then be able to lock the mutex after they're all awoken. Also from the man page:
The thread(s) that are unblocked shall contend for the mutex according
to the scheduling policy (if applicable), and as if each had called
pthread_mutex_lock().
So this means that if 3 threads are blocked on cond and _broadcast is called, all 3 threads will wake up, but only 1 can grab the mutex. The other 2 will still be stuck in pthread_cond_wait, waiting on a signal. Because of this, they don't see stop set to 1, and exit_handler (I'm assuming a Ctrl+c software signal?) is done signaling, so the remaining threads that lost the _broadcast competition are stuck in limbo, waiting on a signal that will never come, and unable to read that the stop flag has been set.
I think there are 2 options to work-around/fix this:
Use pthread_cond_timedwait. Even without being signaled, this will return from waiting at the specified time interval, see that stop == 1, and then exit.
Add pthread_cond_signal or pthread_cond_broadcast at the end of your worker function. This way, right before a thread exits, it will signal the cond variable allowing any other waiting threads to grab the mutex and finish processing. There is no harm in signaling a conditional variable if no threads are waiting on it, so this should be fine even for the last thread.
EDIT: Here is an MCVE that proves (as far as I can tell) that my answer above is wrong, heh. As soon as I press Ctrl+c, the program exits "immediately", which says to me all the threads are quickly acquiring the mutex after the broadcast, seeing that stop is false, and exiting. Then main joins on the threads and it's process over.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#define NUM_THREADS 3
#define STACK_SIZE 10
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c = PTHREAD_COND_INITIALIZER;
volatile bool stop = false;
int stack[STACK_SIZE] = { 0 };
int sp = 0; // stack pointer,, also doubles as the current stack size
void SigHandler(int sig)
{
if (sig == SIGINT)
{
stop = true;
}
else
{
printf("Received unexcepted signal %d\n", sig);
}
}
void* worker(void* param)
{
long tid = (long)(param);
while (stop == false)
{
// acquire the lock
pthread_mutex_lock(&m);
while (sp <= 0) // sp should never be < 0
{
// there is no data in the stack to consume, wait to get signaled
// this unlocks the mutex when it is called, and locks the
// mutex before it returns
pthread_cond_wait(&c, &m);
}
// when we get here we should be guaranteed sp >= 1
printf("thread %ld consuming stack[%d] = %d\n", tid, sp-1, stack[sp-1]);
sp--;
pthread_mutex_unlock(&m);
int sleepVal = rand() % 10;
printf("thread %ld sleeping for %d seconds...\n", tid, sleepVal);
sleep(sleepVal);
}
pthread_exit(NULL);
}
int main(void)
{
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
srand(time(NULL));
for (long i=0; i<NUM_THREADS; i++)
{
int rc = pthread_create(&threads[i], &attr, worker, (void*)i);
if (rc != 0)
{
fprintf(stderr, "Failed to create thread %ld\n", i);
}
}
while (stop == false)
{
// produce data in bursts
int numValsToInsert = rand() % (STACK_SIZE - sp);
printf("main producing %d values\n", numValsToInsert);
// acquire the lock
pthread_mutex_lock(&m);
for (int i=0; i<numValsToInsert; i++)
{
// produce values for the stack
int val = rand() % 10000;
// I think this should already be guaranteed..?
if (sp+1 < STACK_SIZE)
{
printf("main pushing stack[%d] = %d\n", sp, val);
stack[sp++] = val;
// signal the workers that data is ready
//printf("main signaling threads...\n");
//pthread_cond_signal(&c);
}
else
{
printf("stack full!\n");
}
}
pthread_mutex_unlock(&m);
// signal the workers that data is ready
printf("main signaling threads...\n");
pthread_cond_broadcast(&c);
int sleepVal = 1;//rand() % 5;
printf("main sleeping for %d seconds...\n", sleepVal);
sleep(sleepVal);
}
for (long i=0; i<NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}

Mutex Threading - Code doesn't seem to Exit Properly

So I have code here which makes two kinds of threads. One kind "produces" data and the other one "consumes" it. There can only be a certain amount of data that can exist at any one time, so the Producers will pause producing once there is a certain amount of data created (ie, when sharedData = BUFFER), and the consumers will pause when sharedData = 0. There is also only so much data that can be made (amount stored in dataleft), and once all the data has been made and consumed, the program should end.
For some reason, the printf() lines I have at the end of the code don't seem to ever trigger. I can't tell if the threads are closed properly or not because of this. It feels like I've done something really stupid, but I can't see the issue.
A couple of definitions at the start:
#define NUMCONSUMERS 4
#define NUMPRODUCERS 4
#define PACKETS 10
#define tryMainlock pthread_mutex_trylock(&dataMutex)
#define openMainlock pthread_mutex_lock(&dataMutex)
#define closeMainlock pthread_mutex_unlock(&dataMutex)
#define waitMainlock pthread_cond_wait(&dataPresentCondition, &dataMutex);
#define signalMainlock pthread_cond_signal(&dataPresentCondition);
#define trydatalock pthread_mutex_trylock(&IsthereDataleft)
#define opendatalock pthread_mutex_lock(&IsthereDataleft)
#define closedatalock pthread_mutex_unlock(&IsthereDataleft)
pthread_mutex_t dataMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t dataPresentCondition = PTHREAD_COND_INITIALIZER;
pthread_mutex_t IsthereDataleft = PTHREAD_MUTEX_INITIALIZER;
int sharedData=0; //amount of data present
int BUFFER = 5;
int dataleft=PACKETS;
The Main Function:
int main(int argc, char **argv)
{
int rc;
int i;
pthread_t consumer[NUMCONSUMERS];
pthread_t producer[NUMPRODUCERS];
rc = opendatalock; //lock to determine whether there's any point waiting for data
for (i=0; i <NUMPRODUCERS; i++) { //Build up the producers
rc = pthread_create(&producer[i], NULL, Producer, (void *)i);
if (rc)
printf("Error building Producer Thread: %x\n", i);
}
for (i=0; i <NUMCONSUMERS; i++) { //Build up the consumers
rc = pthread_create(&consumer[i], NULL, Consumer, (void *)i);
if (rc)
printf("Error building Consumer Thread: %x\n", i);
}
printf("All Producers and Consumers created\n");
for (i=0; i <NUMPRODUCERS; i++) { //Join up the producers
rc = pthread_join(producer[i], NULL);
if (rc)
printf("Error: Producer %x: Failed to join\n", i);
}
rc = closedatalock; //producers finished, no data left to make
printf("datalock closed, consumers finishing...\n");
for (i=0; i <NUMCONSUMERS; i++) { //Join up the consumers
rc = pthread_join(consumer[i], NULL);
if (rc)
printf("Error: Consumer %x: Failed to join\n", i);
}
rc = pthread_mutex_destroy(&dataMutex);
rc = pthread_cond_destroy(&dataPresentCondition);
rc = pthread_mutex_destroy(&IsthereDataleft);
printf("All Threads finished. Exiting....\n");
return 0;
}
The Consumer Thread:
void *Consumer(void *threadid){
int rc;
printf("Consumer Thread %x: Created\n", (int)threadid);
while (1)
{
printf("Consumer %x: Entering Loop\n", (int)threadid);
rc = openMainlock; //take hold of main lock
if (rc)
{
printf("Consumer %x: Waiting...\n", (int)threadid);
rc = waitMainlock; //if main lock is taken, wait
if (rc) //if wait fails, exit the thread.
{
printf("Consumer Thread %x: wait for Main Lock failed\n", threadid);
exit(0);
}
}
while (sharedData == 0) //if the buffer is empty
{
rc = trydatalock;
if (!rc)
{
printf("Consumer %x: Completed. Exiting...\n");
exit(0);
}
rc = closeMainlock;
if (rc)
{
printf("code.\n");
}
rc = waitMainlock;
if (rc)
{
printf("code.\n");
}
}
sharedData--;
rc = closeMainlock;
rc = signalMainlock;
if (rc)
{
printf("code.\n");
}
printf("Consumer %x: Releasing Lock\n", (int)threadid);
}
}
And the Producer Thread:
void *Producer(void *threadid){
int rc;
printf("Producer Thread %x: Created\n", (int)threadid);
while (1)
{
printf("Producer %x: Entering Loop\n", (int)threadid);
rc = openMainlock; //take hold of the lock
if (rc) //if lock is currently being used by a consumer or a producer
{
printf("Producer %x: Waiting...\n", (int)threadid);
rc = waitMainlock; //wait here until lock is released
if (rc)
{
printf("Producer Thread %x: wait for Main Lock failed\n", threadid);
exit(0);
}
}
if (!dataleft) //If there's no data left to add to the stream, close the thread
{
printf("Producer Thread %x: Completed, exiting...\n", (int)threadid);
exit(0);
}
while (sharedData >=BUFFER)
{
rc = closeMainlock;
if (rc)
{
printf("code.\n");
}
rc = waitMainlock;
if (rc)
{
printf("code.\n");
}
}
printf("Producer %x: Lock Acquired\n", (int)threadid);
sharedData++;
dataleft--;
rc = closeMainlock;
rc = signalMainlock;
if (rc)
{
printf("code.\n");
}
printf("Producer %x: Releasing Lock\n", (int)threadid);
}
}
Check out this piece of code:
if (!rc)
{
printf("Consumer %x: Completed. Exiting...\n");
exit(0);
}
If the consumer has finished, the process(!) is terminated. You need to use pthread_exit() instead, or simply return from the thread function.
Then, there is also
../nptl/pthread_mutex_lock.c:80:
__pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.
which I got a few times running the code. That could be caused by e.g. double unlock or some other invalid use. I'd start with cleaning up the weird macros, so that you have a free view on the logic of the program itself.
Also, one important advise concerning mutexes: Always document precisely which data should be protected by the mutex. The point is that it's not always clear and getting this wrong means that you accidentally access data without synchronization. In order to make this very clear, use a structure like here:
struct {
pthread_mutex_t mutex;
pthread_cond_t cond;
int data;
} synced_data = {
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_COND_INITIALIZER,
0
};
Actually, it's not just about the shared data that documentation is important. Consider for example IsthereDataleft: This is a mutex but it doesn't guard anything, right? Instead, it is used to signal to the started threads that there is nothing left to do, right? Documenting this not only helps others to understand your code but it makes sure that you understand yourself what the intention is. Sometimes, while trying to explain it, you will then find yourself that something doesn't make sense.
Something seems to be awry with your use of openMainlock, which expands to a pthread_mutex_lock call.
One one hand, you shouldn't expect to ever get a non-zero return value from openMainlock: pthread_mutex_lock should either return zero (lock acquired) or block, unless the mutex is not initialised or is an error-checking mutex.
Further, once the lock is acquired, if the producer is done, i.e. dataleft is zero, the thread calls exit(0), which will terminate the whole process rather than terminating the thread. pthread_exit should be used instead, or just return from the function, but note that at this point you still own the main lock, which won't be released.

Why does pthread_cond_signal sometimes not work?

My program performs "thread synchronization" using pthread_cond_wait and pthread_cond_signal. It seems to fail about one in 20 times.
I have a shared variable count which is initialized to 0.
One thread increments count until count is 20 , then signals a condition variable.
The code is below.
void* inc_count(void *parm)
{
int i;
for(i = 0 ; i <25; i ++)// adds count to 25
{
pthread_mutex_lock(&mutex1);
count ++;
printf("Thread %lld , count = %d\n",(long long int)pthread_self(),count);
if(count == 20)
{
pthread_cond_signal(&cond);
printf("Thread %lld sends a signal!\n",(long long int)pthread_self());
}
pthread_mutex_unlock(&mutex1);
}
pthread_exit(NULL);
}
void* watch_count(void *parm)
{
while(count < 20)
{
pthread_mutex_lock(&mutex1);
pthread_cond_wait(&cond,&mutex1);
printf("Thread %lld receives the signal!\n",(long long int)pthread_self());
}
pthread_mutex_unlock(&mutex1);
pthread_exit(NULL);
}
int main()
{
pthread_t pt1,pt2,pt3,pt4;
pthread_mutex_init(&mutex1,NULL);
pthread_mutex_init(&mutex2,NULL);
pthread_cond_init(&cond,NULL);
pthread_create(&pt1,NULL,inc_count,NULL);
pthread_create(&pt2,NULL,watch_count,NULL);
pthread_join(pt1,NULL);
pthread_join(pt2,NULL);
}
From the picture, you can see that thread pt2 didn't receive the signal, why?
Your watch_count() function has problems:
You're locking the mutex inside a while loop and only unlocking outside it (could try to lock more than once without unlocking)
You don't hold the mutex when checking count < 20
To fix it, you need lock the mutex before the loop instead of inside it:
pthread_mutex_lock(&mutex1);
while(count < 20)
{
pthread_cond_wait(&cond,&mutex1);
printf("Thread %lld receives the signal!\n",(long long int)pthread_self());
}
pthread_mutex_unlock(&mutex1);
That will keep you from locking the mutex more than once before unlocking, and ensure that count can't be modified and the signal can't be sent between the test in the while condition and the pthread_cond_wait (inc_count()'s change to count and sending the signal would have to occur either before the while loop, or during the pthread_cond_wait()).
Even with those changes, there's still the possibility that the wait won't happen at all if count is already 20 by the time watch_count() checks it, though.
#Dmitri's diagnosis at the end of his comment is the likely cultprit IMO: it's possible that your inc_count thread gets past 20 before the watch_count thread first checks the while condition.
Why use the while loop at all? When inc_count sends the signal, you already know that the count is over 20, so why check for it?
My solution is to do some handshaking and make sure that watch_count enters its wait condition before inc_count starts counting. To achieve this, you need to make sure that the following things happen in order:
inc_count enters its code first and then waits for watch_count to initialize
watch_count enters its code and signals inc_count that it's ready to go
watch_count waits for inc_count to signal it
inc_count starts counting and signals watch_count when it gets to 20
I achieved this by grabbing a mutex before starting either thread, then counting on the first thread to enter its "ready and waiting" condition before starting the second thread. When the second thread is ready it signals the first thread to go ahead and start counting, here's my code:
void* inc_count(void *parm)
{
// holding this mutex on entry;
pthread_mutex_t* m = parm;
int i;
// wait for the watch_count thread to be ready
pthread_cond_wait(&init_cond, m);
pthread_mutex_unlock(m);
// start counting
for(i = 0 ; i < 10000; i ++)
{
pthread_mutex_lock(&count_mutex);
count++;
printf("Thread %lld , count = %d\n",
(long long int) pthread_self(),
count);
if(count == 20)
{
pthread_cond_signal(&count_cond);
printf("Thread %lld sends a signal!\n",
(long long int)pthread_self());
}
pthread_mutex_unlock(&count_mutex);
}
pthread_exit(NULL);
}
void* watch_count(void *parm)
{
// holding this mutex on entry
pthread_mutex_t* m = parm;
pthread_cond_signal(&init_cond); // tell inc_count that you're ready
pthread_cond_wait(&count_cond,m); // wait for him to get to 20
pthread_mutex_unlock(m);
pthread_mutex_lock(&count_mutex);
printf("Thread %lld receives the signal! count == %d\n",
(long long int)pthread_self(),
count);
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}
int main()
{
pthread_t pt1,pt2;
pthread_mutex_t init_mutex, count_mutex;
pthread_mutex_init(&init_mutex,NULL);
pthread_mutex_init(&count_mutex,NULL);
pthread_cond_init(&init_cond,NULL);
pthread_cond_init(&count_cond,NULL);
// this mutex is released when inc_count has initialized
pthread_mutex_lock(&init_mutex);
pthread_create(&pt1,NULL,inc_count,(void *) &init_mutex);
// this mutex is released when watch-count has initialized
pthread_mutex_lock(&init_mutex);
pthread_create(&pt2,NULL,watch_count,(void *) &init_mutex);
pthread_join(pt1,NULL);
pthread_join(pt2,NULL);
}

How to use mutexes in C

I am confused about use of multiple mutexes in C.
int main() {
pthread_t thread1;
char *message1 = "Thread 1";
int r;
pthread_mutex_init(&mutex1, NULL);
pthread_mutex_init(&mutex2, NULL);
pthread_mutex_lock(&mutex1);
r = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
printf("Parent 1\n");
pthread_mutex_lock(&mutex2);
printf("Parent 2\n");
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
pthread_join( thread1, NULL);
printf("Thread 1 returns: %d\n",r);
return 0;
}
void *print_message_function( void *str ) {
pthread_mutex_lock(&mutex1);
char *message;
message = (char *) str;
printf("Child 1 received message: %s \n", message);
pthread_mutex_lock(&mutex2);
printf("child 2\n");
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
return NULL;
}
output is
Parent 1
Parent 2
Child 1 received message: Thread 1
child 2
Thread 1 returns: 0
what i want is
Parent 1
Child 1 received message: Thread 1
Parent 2
child 2
Thread 1 returns: 0
When you call pthread_create you have already locked mutex1. That means that every other thread that calls pthread_mutex_lock(&mutex1); will wait for the mutex to be unlocked. That is what happen when you create a second thread: mutex1 is already locked, so the second thread cannot enter the critical section but need to wait for the mutex to be unlocked. That happens at the end of the main function.
You'll need to reorganize your code to get the output you desire.
However, to obtain such a result you should check synchronization systems, such semaphores or condition variables; they will provide a clearer and easier way to synchronize threads.
You may also check this tutorial: POSIX Threads Programming
A simple solution using semaphores (not tested, but it should work):
#include <stdio.h>
#include <semaphore.h>
sem_t sem1, sem2;
void* f(void* str) {
sem_wait(&sem1);
printf("Child 1 received message: %s \n",(char*)str);
sem_post(&sem2);
sem_wait(&sem1);
printf("Child 2\n");
return NULL;
}
int main (int argc, const char * argv[]) {
pthread_t thread;
char* message = "Thread 1";
int r;
sem_init(&sem1,0,0);
sem_init(&sem2,0,0);
r = pthread_create(&thread, NULL, f, (void*)message);
sem_post(&sem1);
sem_wait(&sem2);
printf("Parent 2\n");
sem_post(&sem1);
pthread_join(thread1, NULL);
printf("Thread 1 returns: %d\n",r);
return 0;
}
Mutexes alone aren't suitable for performing the kind of closely-interlocked execution that you want - their normal use is for protecting access to a shared data structure. This is because they're designed for saying "Thing A shouldn't happen at the same time as Thing B", but they don't say anything about whether Thing A or Thing B happens first or second.
You could use mutexes and condition variables, but in this case your problem is most closely matched by a pthreads Barrier object:
#include <stdio.h>
#include <pthread.h>
pthread_barrier_t barrier;
void *print_message_function( void *str )
{
char *message;
message = (char *) str;
pthread_barrier_wait(&barrier); /* Barrier point 1 */
/* (wait until parent prints first message) */
printf("Child 1 received message: %s \n", message);
pthread_barrier_wait(&barrier); /* Barrier point 2 */
/* (allow parent to proceed and print second message) */
pthread_barrier_wait(&barrier); /* Barrier point 3 */
/* (wait for parent to print second message) */
printf("child 2\n");
return NULL;
}
int main()
{
pthread_t thread1;
char *message1 = "Thread 1";
int r;
pthread_barrier_init(&barrier, NULL, 2);
r = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
printf("Parent 1\n");
pthread_barrier_wait(&barrier); /* Barrier point 1 */
/* (allow child to proceed and print first message) */
pthread_barrier_wait(&barrier); /* Barrier point 2 */
/* (wait for child to print first message) */
printf("Parent 2\n");
pthread_barrier_wait(&barrier); /* Barrier point 3 */
/* (allow child to proceed and print second message) */
pthread_join( thread1, NULL);
/* (wait for child to exit) */
printf("Thread 1 returns: %d\n",r);
return 0;
}
Note that it is not usual to try to tightly interlock the execution of threads in this way - really, you've gone to great pains to ensure that the threads don't execute in parallel at all, which is the whole point of threads in the first place. If you find yourself doing this in a real project, it's a sign that you ought to carefully re-think your design.
I think you need to unlock mutex1 sooner. You unlock it after the printf("Parent 2\n"); so thread1 is still locked waiting for pthread_mutex_lock(&mutex1);.
When thread1 starts it's first step is to lock while it waits for mutual exclusion (clue's in the name) lock on mutex1. So it's paused.
Then you :
printf("Parent 1\n");
pthread_mutex_lock(&mutex2); <-- lock 2 is unleased but thread one is waiting on mutex1
printf("Parent 2\n");

Resources