My intention is to let send() omit signal when the global counter is odd, and broadcast when even. Then there are 2 recv() thread, waiting for signal. In case of signal, only one of the recv() thread can receive it; in case of broadcast, both may receive it.
But my result shows me that both recv() received the same odd number, which should not happen.
Is the global counter and the signal tightly coupled in my code?
edit:
I think I get answer to this question. After a recv() thread receives signal, it will try to lock the mutex associated with the condition variable again, but it may need to wait because the mutex may have already been locked by other thread. During the waiting period, the global count may be changed, so the global count it finally prints is different from the one when it received signal.
Also, in my code, even send() send broadcast, multiples recv() threads actually can not handle the signal concurrently, because they are still exclusive to each other because they share the same mutex
end of edit
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int n = 0;
int count = 0;
void* recv(void *name)
{
while(1)
{
pthread_mutex_lock(&mutex);
// wait for signal
pthread_cond_wait(&cond, &mutex);
count++;
if(count > 10)
{
printf("number %d terminate %s\n", n, (char*)name);
}
else
{
printf("%s gets number:%d\n", (char*)name, n);
}
pthread_mutex_unlock(&mutex);
if(count > 10)
{
return (NULL);
}
}
}
void* send(void *ptr)
{
while(1)
{
pthread_mutex_lock(&mutex);
n++;
// odd: signal
// even: broadcast
if(n%2)
pthread_cond_signal(&cond);
else
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
}
int main(int argc, char *argv[])
{
pthread_t t1, t2, t3;
char *name1 = "t1";
char *name2 = "t2";
pthread_create(&t1, NULL, recv, (void *) name1);
pthread_create(&t2, NULL, recv, (void *) name2);
pthread_create(&t3, NULL, send, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_cancel(t3);
return 0;
}
Output, note the first 2 lines:
t2 gets number:12493
t1 gets number:12493
t1 gets number:12534
t2 gets number:12534
t1 gets number:12623
t1 gets number:12624
t2 gets number:12666
t1 gets number:12666
t2 gets number:12713
t1 gets number:12713
number 12770 terminate t2
number 12998 terminate t1
After a broadcast wakeup, there is no guarantee that the threads will be scheduled as:
or
It is entirely possible that you get:
…in which t3 increments
nto an odd value and wakes up t1, and t2 and t1 then both print that odd number.If you want to closely interlock execution like this you will need to introduce more synchronisation.