将全球价值与信号联系起来

时间:2011-10-27 10:05:12

标签: c synchronization pthreads

我的目的是让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

3 个答案:

答案 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都被唤醒了很多次,因此两个打印值都是。