Переменные условия при печати последовательности слов (потоков) - PullRequest
0 голосов
/ 08 мая 2020

У меня есть программа потока C, которая должна многократно печатать следующую последовательность слов:

one two three one two three one two three...

Я хочу проверить, как это можно сделать с помощью переменных условия, поэтому я использую следующий код:

#include <stdio.h>
#include <pthread.h>
#include <string.h>

pthread_cond_t c1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t c2 = PTHREAD_COND_INITIALIZER;
pthread_cond_t c3 = PTHREAD_COND_INITIALIZER;

pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;

char arr[15] = "one";

void *printS(void *str)
{
    while(1)
    {
        pthread_mutex_lock(&m);

        if ( strcmp(arr,str) != 0)
        {
            if(strcmp("one",str) == 0)
            {
                pthread_cond_wait(&c1, &m);
            }
            else if(strcmp("two",str) == 0)
            {
                pthread_cond_wait(&c2, &m);
            }
            else if(strcmp("three",str) == 0)
            {
                pthread_cond_wait(&c3, &m);
            }

        }
        printf("%s  ", (char*)str);

        if (strcmp("one",arr) == 0)
        {
            strcpy(arr,"two");
            pthread_cond_signal(&c2);
        }
        else if (strcmp("two", arr) == 0)
        {
            strcpy(arr,"three");
            pthread_cond_signal(&c3);
        }
        else if (strcmp("three", arr) == 0)
        {
            strcpy(arr,"one");
            pthread_cond_signal(&c1);
        }
        pthread_mutex_unlock(&m);
    }
    return NULL;
}

int main()
{
    pthread_t t1, t2, t3;
    const char ch1[] = "one";
    const char ch2[] = "two";
    const char ch3[] = "three";

    pthread_mutex_init(&m,0);
    pthread_cond_init(&c1, 0);
    pthread_cond_init(&c2, 0);
    pthread_cond_init(&c3, 0);

    pthread_create(&t1, NULL, printS, (void *)ch1);
    pthread_create(&t2, NULL, printS, (void *)ch2);
    pthread_create(&t3, NULL, printS, (void *)ch3);

    pthread_join(t1, 0);
    pthread_join(t2, 0);
    pthread_join(t3, 0);

    while(1);
    return 0;
}

Однако с этим кодом у меня есть следующий (нежелательный) вывод:

three three three three three three three one two three one two three one tho three three three three three three

Кажется, я не могу найти, что не так с синхронизацией или структурой код. Любая помощь приветствуется, спасибо !!

1 Ответ

0 голосов
/ 08 мая 2020

Как указано в общем комментарии, вам нужен один мьютекс, одно резюме, и все. Каждый поток уже получает собственное тестовое значение предиката. Все, что вам нужно сделать, это убедиться, что мьютекс зафиксирован (путем начальной записи или выхода из pthread_cond_wait) и проверить состояние предиката, чтобы действовать соответствующим образом. После печати, затем изменения предиката (строки), широковещательной рассылки другим потокам при изменении условия и затем повторного цикла. Также блокировка мьютекса должна быть перед вводом while-l oop. Cond-wait при необходимости разблокирует / заблокирует его.

#include <stdio.h>
#include <pthread.h>
#include <string.h>

pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;

char arr[15] = "one";

void *printS(void *str)
{
    pthread_mutex_lock(&m);
    while(1)
    {
        // mutex is latched already
        while (strcmp(arr,str) != 0)
        {
            // this will unlatch the mutex and begin waiting on cv
            pthread_cond_wait(&cv, &m);
        }

        // mutex is once-again latched.
        printf("%s  ", (char*)str);

        // change string accordingly
        if (strcmp("one",arr) == 0)
            strcpy(arr,"two");

        else if (strcmp("two", arr) == 0)
            strcpy(arr,"three");

        else if (strcmp("three", arr) == 0)
            strcpy(arr,"one");

        // and tell everyone waiting something happened.
        // they will wake up as soon as we hit the next wait.
        pthread_cond_broadcast(&cv);
    }

    // will never be reached, but good form nonetheless.
    pthread_mutex_unlock(&m);
    return NULL;
}

int main()
{
    pthread_t t1, t2, t3;
    char ch1[] = "one";
    char ch2[] = "two";
    char ch3[] = "three";

    pthread_create(&t1, NULL, printS, ch1);
    pthread_create(&t2, NULL, printS, ch2);
    pthread_create(&t3, NULL, printS, ch3);

    pthread_join(t1, 0);
    pthread_join(t2, 0);
    pthread_join(t3, 0);

    fgetc(stdin);
    return 0;
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...