patterncMinor
Simple mutex and conditional variable signal in C
Viewed 0 times
simplemutexsignalconditionalandvariable
Problem
I'm new to multithreading in C so I made a toy program that uses a mutex and a conditional variable to communicate between two threads.
```
#include
#include "errors.h"
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int predicate_value = 0;
void do_work(void work) {
int status = 0;
int i = 0;
while (1) {
status = pthread_mutex_lock(&mutex);
if (status != 0) {
err_abort(status, "Lock mutex");
}
while (predicate_value == 0) {
printf("%s\n", "waiting");
status = pthread_cond_wait(&cond, &mutex);
if (status != 0) {
err_abort(status, "Wait on condition");
}
}
if (predicate_value != 0) {
printf("doing some work: %d\n", i);
++i;
predicate_value = 0;
}
status = pthread_mutex_unlock(&mutex);
if (status != 0) {
err_abort(status, "Unlock mutex");
}
}
}
int main () {
int status = 0;
pthread_t work_thread_id;
status = pthread_create(&work_thread_id, NULL, do_work, NULL);
if (status != 0) {
err_abort(status, "Create work thread");
}
while (1) {
if (predicate_value == 0) {
status = pthread_mutex_lock(&mutex);
if (status != 0) {
err_abort(status, "Lock mutex main");
}
printf("%s\n", "changed value");
predicate_value = 1;
status = pthread_cond_signal(&cond);
if (status != 0) {
err_abort(status, "signal condition");
}
status = pthread_mutex_unlock(&mutex);
if (status != 0) {
err_abort(status, "Unlock mutex main");
}
do_work performs a task every 1 second (task could take longer than 1 second). Is this implementation free from deadlocks and race conditions? Anything else I might be missing? ```
#include
#include "errors.h"
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int predicate_value = 0;
void do_work(void work) {
int status = 0;
int i = 0;
while (1) {
status = pthread_mutex_lock(&mutex);
if (status != 0) {
err_abort(status, "Lock mutex");
}
while (predicate_value == 0) {
printf("%s\n", "waiting");
status = pthread_cond_wait(&cond, &mutex);
if (status != 0) {
err_abort(status, "Wait on condition");
}
}
if (predicate_value != 0) {
printf("doing some work: %d\n", i);
++i;
predicate_value = 0;
}
status = pthread_mutex_unlock(&mutex);
if (status != 0) {
err_abort(status, "Unlock mutex");
}
}
}
int main () {
int status = 0;
pthread_t work_thread_id;
status = pthread_create(&work_thread_id, NULL, do_work, NULL);
if (status != 0) {
err_abort(status, "Create work thread");
}
while (1) {
if (predicate_value == 0) {
status = pthread_mutex_lock(&mutex);
if (status != 0) {
err_abort(status, "Lock mutex main");
}
printf("%s\n", "changed value");
predicate_value = 1;
status = pthread_cond_signal(&cond);
if (status != 0) {
err_abort(status, "signal condition");
}
status = pthread_mutex_unlock(&mutex);
if (status != 0) {
err_abort(status, "Unlock mutex main");
}
Solution
Needs volatile keyword
The way your program is written,
Another way to avoid the problem is to ensure that you only ever read the variable with the mutex locked.
The way your program is written,
predicate_value needs to be a volatile int instead of a normal int. This is because you are reading it without locking the mutex in main(), and writing to it in do_work() from another thread.Another way to avoid the problem is to ensure that you only ever read the variable with the mutex locked.
Context
StackExchange Code Review Q#149180, answer score: 2
Revisions (0)
No revisions yet.