Связать глобальное значение с сигналом - PullRequest
1 голос
/ 27 октября 2011

Мое намерение состоит в том, чтобы позволить send () пропустить сигнал, когда глобальный счетчик нечетный, и транслировать, когда четный.Затем идут 2 потока recv (), ожидающих сигнала.В случае сигнала только один из потоков recv () может получить его;в случае трансляции оба могут получить его.

Но мой результат показывает мне, что оба recv () получили одно и то же нечетное число, чего не должно быть.

Является ли глобальный счетчик и сигналтесно связаны в моем коде?

edit:

Думаю, я получу ответ на этот вопрос.После того, как поток 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;
}

Выводобратите внимание на первые 2 строки:

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 ]

1 голос
/ 27 октября 2011

После активации широковещательной рассылки нет гарантии, что потоки будут запланированы как:

t1
t2
t3

или

t2
t1
t3

Вполне возможно, что вы получите:

t1
t3
t2

... при котором t3 увеличивает n до нечетного значения и пробуждает t1, а затем t2 и t1 выводят это нечетное число.

Если вы хотите тесно заблокировать выполнение, как это, вам нужно будет ввести больше синхронизации.

1 голос
/ 27 октября 2011

Причина, по которой вы видите этот результат, заключается в том, что вы увеличиваете глобальную переменную n в send(). Если вы увеличите его в recv(), вы увидите другой результат. Причина в том, что каждый поток получает широковещательную рассылку или сигнал, соответственно, один за другим, и печатает результат, но происходит только одна отправка для каждого recv, происходящего для этой отправки.

Если вы хотите, чтобы он подсчитывался отдельно для каждого потока, вы должны увеличить переменную внутри блокировки в recv()

Кстати, это имена других функций c. Вы, вероятно, должны выбрать другие.

0 голосов
/ 27 октября 2011

Функция «сигнал / широковещание» работает асинхронно: send () не отказывается от управления в момент подачи сигнала, а выполняет циклическое переключение своего цикла до тех пор, пока его временной интервал не увеличится.И t1, и t2 просыпались много раз во время timesice send (), поэтому оба значения печати. ​​

...