我的目的是让send()在全局计数器为奇数时省略信号,在偶数时进行广播。然后有2个recv()线程,等待信号。在信号的情况下,只有一个recv()线程可以接收它;在广播的情况下,两者都可以收到它。
但是我的结果告诉我,recv()都收到了相同的奇数,这不应该发生。
全局计数器和信号是否紧密耦合在我的代码中?
编辑
我想我能回答这个问题。在recv()线程收到信号后,它将尝试再次锁定与条件变量关联的互斥锁,但可能需要等待,因为互斥锁可能已被其他线程锁定。在等待期间,全局计数可能会改变,因此它最终打印的全局计数与接收信号时的全局计数不同。
另外,在我的代码中,即使send()发送广播,倍数recv()线程实际上也无法同时处理信号,因为它们仍然是彼此独占的,因为它们共享相同的互斥锁
编辑结束
#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;
}
输出,请注意前两行:
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
答案 0 :(得分:1)
您看到此结果的原因是因为您要在n
中增加全局send()
变量。如果您在recv()
中增加它,则会看到不同的结果。原因是每个线程分别一个接一个地接收广播或信号,并打印结果,但是对于该发送,每个recv只发生一次发送。
如果你想在每个线程的基础上看到它计数,你应该在recv()
顺便说一句,这些是其他c函数的名称。你应该选择其他的。
答案 1 :(得分:1)
广播唤醒后,无法保证将线程安排为:
t1
t2
t3
或
t2
t1
t3
完全有可能得到:
t1
t3
t2
...其中t3将n
递增到奇数值并唤醒t1,然后t2和t1都打印出奇数。
如果你想密切联系这样的执行,你需要引入更多的同步。
答案 2 :(得分:0)
信号/广播功能异步工作:send()在发出信号时不会放弃控制,而是循环通过其循环直到其时间片结束。在发送()的时间片期间,t1和t2都被唤醒了很多次,因此两个打印值都是。