printing odd and even number using threads - c

I know there are many examples for my question. However, I want to understand why 1 program that I wrote works and other doesn't.
Here is what I have written.
void * even()
{
while(1)
{
pthread_mutex_lock(&lock);
if(count % 2 == 0)
{
printf("count %d\n",count);
pthread_cond_signal(&cond);
}
else
{
pthread_cond_wait(&cond,&lock);
}
count++;
pthread_mutex_unlock(&lock);
if(count >= 100) return NULL;
}
}
void * odd()
{
while(1)
{
pthread_mutex_lock(&lock);
if(count % 2 == 1)
{
printf("count %d\n",count);
pthread_cond_signal(&cond);
}
else
{
pthread_cond_wait(&cond,&lock);
}
count++;
pthread_mutex_unlock(&lock);
if(count >= 100) return NULL;
}
}
So the above piece of code prints only 0 or 0 and 1 sometimes. However the below code works fine.
void * even()
{
while(1)
{
pthread_mutex_lock(&lock);
if(count % 2 == 0)
{
printf("count %d\n",count);
count++;
pthread_cond_signal(&cond);
}
else
{
pthread_cond_wait(&cond,&lock);
}
pthread_mutex_unlock(&lock);
if(count >= 100) return NULL;
}
}
void * odd()
{
while(1)
{
pthread_mutex_lock(&lock);
if(count % 2 == 1)
{
printf("count %d\n",count);
count++;
pthread_cond_signal(&cond);
}
else
{
pthread_cond_wait(&cond,&lock);
}
pthread_mutex_unlock(&lock);
if(count >= 100) return NULL;
}
}
Thanks a lot.

In the first example, some variation of the below may happen:
even() acquires the lock
even() prints count (which is 0) and signals the condition (though odd() can't wake until even() releases the lock)
even() increments count to 1
even() releases the lock, and odd() wakes.
odd() increments count to 2
odd() releases the lock (but hasn't signalled the condition)
odd() acquires the lock
odd() waits, because count is even (== 2)... now both threads are waiting and neither can signal the condition.
Things may happen slightly differently depending on which thread goes first, but both threads still get stuck in a way similar to the above.
Both examples are unreliable, though, because they don't account for spurious wakeups when waiting for the condition. Normally a loop should be used to retry the wait if the desired wakeup conditions aren't met, holding the lock the whole time so a signal won't be missed:
pthread_mutex_lock(&lock);
/* ...stuff... */
/* Use a loop to restart the wait if it was interrupted early */
while(count % 2 != 0)
pthread_cond_wait(&cond,&lock);
/* ...stuff... */
pthread_mutex_unlock(&lock);

In the first example, in even(), then if count is odd, you pthread_cond_signal odd() to run if count is even. count will be incremented, and the mutex dropped. At this point odd() may run and signal even() before even() ever reaches the pthread_cond_wait(). Now odd() will never again signal even() (because count is now even), and the even()'s pthread_cond_wait() will never exit.
But both of your examples are buggy. You are (last full line) reading count outside the mutex that protects it.

#include <stdio.h>
#include <pthread.h>
#include<iostream>
void *odd(void* data);
void *even(void* data);
static int count=0;
pthread_mutex_t mutex;
pthread_cond_t cond;
int main()
{
pthread_t thread1,thread2;
pthread_create(&thread1,NULL,&even,0);
pthread_create(&thread2,NULL,&odd,0);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
return 0;
}
void *even(void* data)
{
pthread_mutex_lock(&mutex);
while(count< 10)
{
while(count%2!=0)
{
pthread_cond_wait(&cond,&mutex);
}
std::cout<<count;
count++;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
pthread_exit(0);
}
void *odd(void* data)
{
pthread_mutex_lock(&mutex);
while(count<10)
{
while(count%2!=1)
{
pthread_cond_wait(&cond,&mutex);
}
std::cout<<count;
count++;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
pthread_exit(0);
}

Related

How to make thread 2,3 and 4 wait for same signal from thread1?

I have a function to be executed by thread1,2,3,4.... Once thread1 gets access to the function, I use thread_cond for waiting for the other threads. Once thread1 does its work, I send thread_signal to the same cond. Thread2 is executing the function. But after it finishes execution, the other threads don't get access to the function.
Please help me
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
int limit = 0;
pthread_mutex_t mutex[100];
pthread_cond_t cond[100];
pthread_t tid[100];
void *enter()
{
if (limit == 1)
{
printf("waiting\n");
pthread_cond_wait(&cond[1],&mutex[1]);
}
gotofunction();
}
void gotofunction()
{
limit++;
/* Do work */
printf("Doing work\n");
sleep(1);
limit--;
printf("Going to give signal\n");
pthread_cond_signal(&cond[1]);
}
int main()
{
int n,i;
scanf("%d",&n);
for (i=0;i<100;i++)
{
pthread_mutex_init(&mutex[i], NULL);
pthread_cond_init(&cond[i], NULL);
}
for (i=0;i<n;i++)
{
pthread_create(&tid[i], NULL, enter, NULL);
sleep(0.5);
}
for (i=1;i<=n;i++)
{
pthread_join(tid[i], NULL);
}
}
Basically thread1 prints "doing work"
Thread2 prints "doing work"
Then nothing happens for the other threads
You must have the mutex that you passed to pthread_cond_wait() locked at the time you call it. That mutex must also be locked while you check and change the condition that the condition variable is paired with (in this case, limit == 1 is that condition).
You should also use the pattern while (condition) { pthread_cond_wait() } (rather than if (condition)), because the condition variable may wake up without the condition actually being true.
Changing your code to lock the mutex around the accesses to limit, and unlock it while simulating the work, looks like this:
void *enter()
{
pthread_mutex_lock(&mutex[1]);
while (limit == 1)
{
printf("waiting\n");
pthread_cond_wait(&cond[1],&mutex[1]);
}
gotofunction();
pthread_mutex_unlock(&mutex[1]);
return NULL;
}
void gotofunction()
{
limit++;
pthread_mutex_unlock(&mutex[1]);
/* Do work */
printf("Doing work\n");
sleep(1);
pthread_mutex_lock(&mutex[1]);
limit--;
printf("Going to give signal\n");
pthread_cond_signal(&cond[1]);
}
Of course when you check against a limit of 1, you could just use a plain mutex instead - but this scheme could be extended to allow N threads to execute work simultaneously, by changing the condition to while (limit >= N).

pthread_cond_wait and pthread_mutex_lock priority?

I have a multiple read threads and one write thread. If I lock mutex on one of the read threads and send broadcast from it, is it guaranteed that mutex will be locked by write thread waiting on pthread_cond_wait() or is there a possibility that another read thread that is wainting on pthread_mutex_lock() will lock mutex? Main question is does pthread_cond_wait() have priority over pthread_mutex_lock()?
If not, how can I achieve that the mutex will always be locked by write thread on pthread_cond_broadcast()?
Example
Read thread:
pthread_mutex_lock(mutex);
pthread_cond_broadcast(cond);
pthread_mutex_unlock(mutex);
Write thread:
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
Let's assume both threads, read and write, reach the pthread_mutex_lock in the same moment. So, either write thread acquire the mutex on pthread_mutex_lock call, or read thread.
If it would be the write thread, the read one will wait on pthread_mutex_lock. The write, by calling pthread_cond_wait releases mutex and blocks on cond. It is done atomically. So, when read thread is grantex the mutex, we can be sure the the read one waits on cond. So, broadcast on cond reaches the write thread, it no more waits on cond but - still in scope of pthread_cond_wait - tries to get a lock on mutex (hold be read thread). After broadcasting cond the read thread releases the mutex and it goes to write thread. So write thread finally exits from pthread_cond_wait having the mutex locked. Remember to unlock it later.
If it would be the read thread, the write one will wait on pthread_mutex_lock, the read will broadcast a signal on cond then release the mutex. After then the write thread acquires the mutex on pthread_mutex_lock and immediately releases in it pthread_cond_wait waiting for cond (please note, that previous cond broadcast has no effect on current pthread_cond_wait). In the next iteration of read thread it acquires lock onmutex, send broadcast on cond and unlock mutex. It means the write thread moves forward on cond and acquires lock on mutex.
Does it answer your question about priority?
Update after comment.
Let's assume we have one thread (let's name it A for future reference) holding the lock on mutex and few other trying to acquire the same lock. As soon as the lock is released by first thread, there is no predictable which thread would acquire lock. Moreover, if the A thread has a loop and tries to reacquire lock on mutex, there is a chance it would be granted this lock and other threads would keep waiting. Adding pthread_cond_wait doesn't change anything in scope of granting a lock.
Let me quote fragments of POSIX specification (see https://stackoverflow.com/a/9625267/2989411 for reference):
These functions atomically release mutex and cause the calling thread to block on the condition variable cond; atomically here means "atomically with respect to access by another thread to the mutex and then the condition variable". That is, if another thread is able to acquire the mutex after the about-to-block thread has released it, then a subsequent call to pthread_cond_broadcast() or pthread_cond_signal() in that thread shall behave as if it were issued after the about-to-block thread has blocked.
And this is only guarantee given by standard regarding order of operations. Order of granting the lock to other threads is rather unpredictable and it changes depending on some very subtle fluctuation in timing.
For only mutex related code, please play a little with following code:
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *th(void *arg) {
int i;
char *s = arg;
for (i = 0; i < 10; ++i) {
pthread_mutex_lock(&mutex);
printf("%s %d\n", s, i);
//sleep(1);
pthread_mutex_unlock(&mutex);
#if 0
pthread_yield();
#endif
}
return NULL;
}
int main() {
int i;
for (i = 0; i < 10; ++i) {
pthread_t t1, t2, t3;
printf("================================\n");
pthread_create(&t1, NULL, th, "t1");
pthread_create(&t2, NULL, th, " t2");
pthread_create(&t3, NULL, th, " t3");
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
}
return 0;
}
On one machine (single CPU) it always shows whole loop from t3, then t2 and finally from t1. On another (2 cores) the order of threads is more random, but almost always it shows whole loop for each thread before granting the mutex to other thread. Rarely there is a situation like:
t1 8
t1 9
t3 0
t2 0
t2 1
[removed other t2 output]
t2 8
t2 9
t3 1
t3 2
Enable pthread_yield by replacing #if 0 with #if 1 and watch results and check output. For me it works in a way two threads display their output interlaced, then third thread finally has a chance to work. Add another or more thread. Play with sleep, etc. It confirms the random behaviour.
If you wish to experiment a little, compile and run following piece of code. It's an example of single producer - multiple consumers model. It can be run with two parameters: first is the number of consumer threads, second is the length of produced data series. If no parameters are given there is one consumer thread and 120 items to be processed. I also recommend with sleep/usleep in places marked /* play here */: change the value of arguments, remove the sleep at all, move it - when appropriate - to critical section or replace with pthread_yield and observe changes in behaviour.
#define _GNU_SOURCE
#include <assert.h>
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
struct data_t {
int seq;
int payload;
struct data_t *next;
};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
struct data_t *first = NULL, *last = NULL;
int in_progress = 1;
int num_data = 120;
void push(int seq, int payload) {
struct data_t *e;
e = malloc(sizeof(struct data_t));
e->seq = seq;
e->payload = payload;
e->next = NULL;
if (last == NULL) {
assert(first == NULL);
first = last = e;
} else {
last->next = e;
last = e;
}
}
struct data_t pop() {
struct data_t res = {0};
if (first == NULL) {
res.seq = -1;
} else {
res.seq = first->seq;
res.payload = first->payload;
first = first->next;
if (first == NULL) {
last = NULL;
}
}
return res;
}
void *producer(void *arg __attribute__((unused))) {
int i;
printf("producer created\n");
for (i = 0; i < num_data; ++i) {
int val;
sleep(1); /* play here */
pthread_mutex_lock(&mutex);
val = rand() / (INT_MAX / 1000);
push(i, val);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
printf("prod %3d %3d signaled\n", i, val);
}
in_progress = 0;
printf("prod end\n");
pthread_cond_broadcast(&cond);
printf("prod end signaled\n");
return NULL;
}
void *consumer(void *arg) {
char c_id[1024];
int t_id = *(int *)arg;
sprintf(c_id, "%*s c %02d", t_id % 10, "", t_id);
printf("%s created\n", c_id);
while (1) {
struct data_t item;
pthread_mutex_lock(&mutex);
item = pop();
while (item.seq == -1 && in_progress) {
printf("%s waits for data\n", c_id);
pthread_cond_wait(&cond, &mutex);
printf("%s got signal\n", c_id);
item = pop();
}
if (!in_progress && item.seq == -1) {
printf("%s detected end of data.\n", c_id);
pthread_mutex_unlock(&mutex);
break;
}
pthread_mutex_unlock(&mutex);
printf("%s processing %3d %3d\n", c_id, item.seq, item.payload);
sleep(item.payload % 10); /* play here */
printf("%s processed %3d %3d\n", c_id, item.seq, item.payload);
}
printf("%s end\n", c_id);
return NULL;
}
int main(int argc, char *argv[]) {
int num_cons = 1;
pthread_t t_prod;
pthread_t *t_cons;
int i;
int *nums;
if (argc > 1) {
num_cons = atoi(argv[1]);
if (num_cons == 0) {
num_cons = 1;
}
if (num_cons > 99) {
num_cons = 99;
}
}
if (argc > 2) {
num_data = atoi(argv[2]);
if (num_data < 10) {
num_data = 10;
}
if (num_data > 600) {
num_data = 600;
}
}
printf("Spawning %d consumer%s for %d items.\n", num_cons, num_cons == 1 ? "" : "s", num_data);
t_cons = malloc(sizeof(pthread_t) * num_cons);
nums = malloc(sizeof(int) * num_cons);
if (!t_cons || !nums) {
printf("Out of memory!\n");
exit(1);
}
srand(time(NULL));
pthread_create(&t_prod, NULL, producer, NULL);
for (i = 0; i < num_cons; ++i) {
nums[i] = i + 1;
usleep(100000); /* play here */
pthread_create(t_cons + i, NULL, consumer, nums + i);
}
pthread_join(t_prod, NULL);
for (i = 0; i < num_cons; ++i) {
pthread_join(t_cons[i], NULL);
}
free(nums);
free(t_cons);
return 0;
}
I hope I have cleared your doubts and gave you some code to experiment and gain some confidence about pthread behaviour.

How to use mutex to sync this secuence: (A or B)C (A or B) (A or B)C

i'm learning about sync with mutex and have this problem. I need 3 threads, each one print a letter and i've to print the secuence from te tittle in an infinite loop. The idea its that A and B thread make the same thing except the print. My idea was to use a trylock with initial value 1, AorB mutex initial value 1 and C mutex initial value 0. but then realise it only work the first iteration and then write alway 2 (AorB)... Its posible to solve it in this way?
void *rutA(){ //Rut B its the same but print B
while(1){
pthread_mutex_lock(&semAoB);
printf("A");
fflush(stdout);
sleep(1);
if(sem_trywait(&turnoC) == 0){//(AorB)
pthread_mutex_unlock(&semC);
}else{////(AorB)(AorB)
sem_post(&turnoC);
pthread_mutex_unlock(&mutexAoB);
}
}
pthread_exit(NULL);
}
void *rutC(){
while(1){
pthread_mutex_lock(&mutexC);
printf("C");
sleep(1);
fflush(stdout);
pthread_mutex_unlock(&semAoB);
}
pthread_exit(NULL);
}
You can't unlock a mutex in a different thread than the one that locked it.
You can solve this problem either using sempahores, or using mutexes and condition variables - but you should probably not mix the two approaches.
Here's an example of solving it using a mutex and condition variable pair:
int state = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *runA(void *arg)
{
while (1)
{
pthread_mutex_lock(&mutex);
while (state == 1 || state == 4)
pthread_cond_wait(&cond, &mutex);
putchar('A');
fflush(stdout);
if (++state > 4)
state = 0;
pthread_mutex_unlock(&mutex);
pthread_cond_broadcast(&cond);
}
return NULL;
}
void *runB(void *arg)
{
while (1)
{
pthread_mutex_lock(&mutex);
while (state == 1 || state == 4)
pthread_cond_wait(&cond, &mutex);
putchar('B');
fflush(stdout);
if (++state > 4)
state = 0;
pthread_mutex_unlock(&mutex);
pthread_cond_broadcast(&cond);
}
return NULL;
}
void *runC(void *arg)
{
while (1)
{
pthread_mutex_lock(&mutex);
while (state == 0 || state == 2 || state == 3)
pthread_cond_wait(&cond, &mutex);
putchar('C');
fflush(stdout);
if (++state > 4)
state = 0;
pthread_mutex_unlock(&mutex);
pthread_cond_broadcast(&cond);
}
return NULL;
}

Scheduling of Multiple Threads using Mutex and Condition Variable

I'm trying to create four threads printing some message.
I'm facing some issue with synchronisation.
Here is what my main() looks like
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int count = 4;
int main (void)
{
pthread_t thread1, thread2, thread3, thread4;
pthread_create (&thread4, NULL, function4, NULL);
pthread_create (&thread3, NULL, function3, NULL);
pthread_create (&thread2, NULL, function2, NULL);
pthread_create (&thread1, NULL, function1, NULL);
pthread_join (thread1, NULL);
pthread_join (thread2, NULL);
pthread_join (thread3, NULL);
pthread_join (thread4, NULL);
return 0;
}
function1() prints Function 1, function2() prints Function 2 and so on.
Desired Output should be the following:
Function 1
Function 2
Function 3
Function 4
Actual Output:
Function 1
/* Infinitely runs (Deadlock maybe) */
Actual Question:
Can we use one single condition variable for Synchronization of two or more threads ? If so how ?
If not, how do I tackle this problem ?
Here is the definition of function(n)
void *function1 ()
{
while (1)
{
if (count == 4)
{
pthread_mutex_lock (&mutex);
printf("Function 1\n");
count --;
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
void *function2 ()
{
while (1)
{
if (count == 3)
{
pthread_mutex_lock (&mutex);
printf("Function 2\n");
count--;
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
void *function3 ()
{
while (1)
{
if(count == 2)
{
pthread_mutex_lock (&mutex);
printf("Function 3\n");
count--;
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
void *function4 ()
{
while (1)
{
if(count == 1)
{
pthread_mutex_lock (&mutex);
printf("Function 4\n");
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
}
return NULL;
}
After a more clear understanding, I have resolved this issue.
This is a case of race condition.
Things wrong with the code:
Use pthread_cond_broadcast instead ofpthread_cond_signal.
From the man pages
The pthread_cond_broadcast() function shall unblock all threads currently blocked on the specified condition variable cond.
The pthread_cond_signal() function shall unblock at least one of the threads that are blocked on the specified condition variable cond
Not acquiring a lock before checking for if (count == X), Need a
place a lock before that (since count is global/shared variable).
Not placing an unlock if the control goes to else. Since a lock
is already placed (earlier before else), you need to unlock
it.
If you fail to do so, other threads will try to lock a mutex,
that is already locked , leading to race conditions.
Function should be as follow
void *function1 ()
{
while (1)
{
/* Take a lock on the Mutex */
pthread_mutex_lock (&mutex);
if (4 == count)
{
printf("Function 1\n"); /* Perform your task */
count--;
/* Once operation on shared variable (count) is completed, release lock*/
pthread_mutex_unlock (&mutex);
/* Broadcast to other threads about completion of task */
pthread_cond_broadcast (&cond);
return NULL;
}
else
{
/* If count doesnt match, wait on the condition (wait for signal from other threads) */
pthread_cond_wait(&cond, &mutex);
/* Unlock the mutex, since it was locked earlier - else goes to deadlock */
pthread_mutex_unlock (&mutex);
}
}
return NULL;
}
Here is the complete working code.
The change required is simple:
instead of:
else
pthread_cond_wait(&cond, &mutex);
do this:
else {
pthread_mutex_lock (&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock (&mutex);
}
It works for me with these changes, but results in unpredictable behaviour without the changes.
Edit:
This above mentioned simple way still leaves a race condition and doesn't fix the signal vs broadcast problem. To avoid it, the code should be structured like the following:
pthread_mutex_lock (&mutex);
if (count == 4)
{
printf("Function 1\n");
count --;
pthread_mutex_unlock (&mutex);
pthread_cond_broadcast (&cond); // NOTE: broadcast, not signal!
return NULL;
}
else
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock (&mutex);
Note that pthread_cond_broadcast is necessary as you want to wake up all threads.

Semaphores and Deadlocks in C

I'm trying to code the producer/consumer problem using semaphores. I have 3, 1 acting as a mutex, and another 2 for the buffer which the producers and consumers can add/remove from. When adding/removing from the buffer I use the binary semaphore to lock/unlock it so that the global variables aren't subject to any race conditions. The produce semaphore represents how many spots are available in the buffer (how many things can be put into the buffer) while the consumer semaphore represents how many things can be removed from the buffer. I think my logic is wrong cause I always reach a deadlock. Also when I removed the produce and consume semaphores just to test whether or not the program does what its supposed to do, I still get race conditions even though the binary semaphore should be blocking that. What am I doing wrong?
enter code here
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>
#include </usr/include/semaphore.h>
#define MAXITEMS 100
#define PRODUCER_NO 5
#define NUM_PRODUCED 5
void *producer_function (void);
void *consumer_function (void);
void add_buffer (long i);
long get_buffer ();
long sum_value = 0;
long finished_producers;
long buffer[MAXITEMS];
int size = 0;
int front, rear = 0;
pthread_t producerThread[5];
pthread_t consumerThread;
sem_t mutex, produce, consume;
int main(void)
{
int i = 0;
srand (time(NULL));
sem_init (&mutex, 0, 1);
sem_init (&produce, 0, 100);
sem_init (&consume, 0, 0);
for (i = 0; i < 5; i++)
{
pthread_create (&producerThread[i], NULL, (void *) producer_function, NULL);
}
pthread_create (&consumerThread, NULL, (void *) consumer_function, NULL);
for (i = 0; i < 5; i++)
{
pthread_join (producerThread[i], NULL);
}
pthread_join (consumerThread, NULL);
return(0);
}
void *producer_function(void)
{
long counter = 0;
long producer_sum = 0L;
while (counter < NUM_PRODUCED)
{
sem_wait (&mutex);
sem_wait (&produce);
long rndNum = rand() % 10;
producer_sum += rndNum;
add_buffer (rndNum);
sem_post (&consume);
counter++;
if (counter == NUM_PRODUCED)
{
finished_producers++;
}
sem_post (&mutex);
usleep(1000);
}
printf("--+---+----+----------+---------+---+--+---+------+----\n");
printf("The sum of produced items for this producer at the end is: %ld \n", producer_sum);
printf("--+---+----+----------+---------+---+--+---+------+----\n");
return(0);
}
void *consumer_function (void)
{
while (1)
{
sem_wait (&mutex);
sem_wait (&consume);
long readnum = get_buffer();
sem_post (&produce);
sum_value += readnum;
sem_post (&mutex);
//printf ("%ld\n", sum_value);
if ((finished_producers == PRODUCER_NO) && (size == 0))
{
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("The sum of the all produced items at the end is: %ld \n", sum_value);
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
break;
}
}
}
void add_buffer(long i){
buffer[rear] = i;
rear = (rear+1) % MAXITEMS;
size++;
}
long get_buffer(){
long v;
v = buffer[front];
front = (front+1) % MAXITEMS;
size--;
return v;
}
user2929779,
I think its essential to not have the mutex locked, when waiting for a consume notification in the consumer, or vice versa a produce notification in the producer. Imagine you're getting blocked because of waiting for a consume notification, and no producer was able to publish such a notification then your consumer keeps the mutex locked and no producer ever gets the chance to produce a new item...
So the order is important here:
1.) First wait for notification from remote side
2.) lock mutex
3.) modify global data
4.) release mutex
5.) notify remote side
Try this instead:
void *producer_function(void)
{
long counter = 0;
long producer_sum = 0L;
while (counter < NUM_PRODUCED)
{
sem_wait (&produce);
sem_wait (&mutex);
long rndNum = rand() % 10;
producer_sum += rndNum;
add_buffer (rndNum);
counter++;
if (counter == NUM_PRODUCED)
{
finished_producers++;
}
sem_post (&mutex);
sem_post (&consume);
usleep(1000);
}
printf("--+---+----+----------+---------+---+--+---+------+----\n");
printf("The sum of produced items for this producer at the end is: %ld \n", producer_sum);
printf("--+---+----+----------+---------+---+--+---+------+----\n");
return(0);
}
void *consumer_function (void)
{
while (1)
{
sem_wait (&consume);
sem_wait (&mutex);
long readnum = get_buffer();
sum_value += readnum;
if ((finished_producers == PRODUCER_NO) && (size == 0))
{
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("The sum of the all produced items at the end is: %ld \n", sum_value);
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
break;
}
sem_post (&mutex);
sem_post (&produce);
//printf ("%ld\n", sum_value);
}
return(0);
}
P.S. For now ignoring return values of system calls just to show example implementation...
P.S.S. See also pseudo code on wiki http://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem#Using_semaphores ...

Resources