I want to create a program where there are 2 threads reader and writer.
Both reader and writer runs for 10 iterations.
I need a synchronization mechanism that can enable reader and writer execute alternatively.
I tried only with mutex but it did not work. So I used conditional wait, still I could not achieve the results and the code is in infinite wait state. Below is the code that I tried.
int my_global = 0;
int write_flag = 0;
pthread_mutex_t mutex;
pthread_cond_t mycond;
void *reader() {
for(int j=0;j<10;j++){
pthread_mutex_lock(&mutex);
printf("nReader - value of global is %d & write flag is %d and j is %d",my_global,write_flag,j);
write_flag = 1;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&mycond);
// sleep(1);
}
}
void *writer(){
for(int k=0;k<10;k++){
pthread_mutex_lock(&mutex);
printf("nstarted writer");
while(write_flag!=1){
pthread_cond_wait(&mycond,&mutex);
}
write_flag = 0;
my_global++;
printf("nwriter done and writeflag is %d and global is %d and k is %d",write_flag,my_global,k);
pthread_mutex_unlock(&mutex);
}
}
int main()
{
pthread_t my_reader;
pthread_t my_writer;
pthread_cond_init(&mycond,NULL);
pthread_mutex_init(&mutex,NULL);
if (pthread_create(&my_reader, NULL, &reader, NULL) != 0) {
perror("Failed to create thread");
}
if (pthread_create(&my_writer, NULL, &writer, NULL) != 0) {
perror("Failed to create thread");
}
if (pthread_join(my_reader, NULL) != 0) {
perror("Failed to join thread");
}
if (pthread_join(my_writer, NULL) != 0) {
perror("Failed to join thread");
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&mycond);
return 0;
}
Mughunth Srinivasan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
6
You forgot to wait in the writer.
Imagine if you had a queue instead of a single variable.
What do the threads need to wait for?
- The writer must wait for space to be available in the queue.
- The reader must wait for items to be available in the queue.
my_global
can be seen as a queue of one element if it’s paired with a flag indicating the number of elements in the queue i.e. if there’s an element in my_global
waiting to be consumed.
Rather than hardcode ten iterations in the reader, I would add the following condition:
- The reader must wait for writer to have finished adding items.
This will require a flag indicating whether the writer is done or not.
ok, now we have all the elements we need.
Our shared variables are going to be
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
// Shared variables access-controlled by `mutex`.
int done = 0;
int buffer_full = 0;
int buffer;
Our writer’s wait loop is going to be
while ( buffer_full )
pthread_cond_wait( &cond, &mutex );
Our reader’s wait loop is going to be
while ( !buffer_full && !done )
pthread_cond_wait( &cond, &mutex );
1
In addition to the issues already mentioned, you have a severe bug in the form of wrong callback function format. Pthreads require a function of the form void* func (void*)
. You are using void* func ()
.
The reason why you aren’t getting any compiler warning is because in older C versions, an empty parameter list function pointer is compatible with a function pointer with the same type but any parameter list. But just because the pointer types are compatible doesn’t mean it will work, because the functions might end up using the wrong calling convention, which in turn can lead to mysterious run-time crashes etc.
If you compile in C23 mode, this bug will get detected.