Производители проблемных вопросов потребителей с использованием потоков Linux

#c #linux #pthreads #mutex

#c #linux #pthreads #мьютекс

Вопрос:

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

  1. В этой программе есть переменная с именем integer item_program . Есть также потребители и производители. Производитель, потребитель, выполняется как отдельные потоки. Производитель увеличивает значение переменной item_count .Потребитель уменьшает значение переменной item_count .
  2. Потоками этой программы являются производители (2), производители (3), потребители (1), потребители (2) и потребители (3). Производитель (2) увеличивает значение item_count на 2. Потребитель (3) уменьшает значение item_count на 3.
  3. Эта программа выполняется в общей сложности 60 секунд, а значение item_count всегда больше 0 и меньше 10.
  4. Производители и потребители должны печатать следующий формат на консоли при увеличении или уменьшении значения item_count .

=> [количество идентификаторов потоков]: до подсчета: ?, после подсчета: ?

ex1) [20304 producer (3) ] До подсчета: 2, после подсчета: 5

пример 2) [20355 корректор (2) ] До подсчета: 5, после подсчета: 3

  1. Значение предшествующего подсчета предыдущего оператора вывода и предшествующего подсчета последующего оператора вывода не должны совпадать.

пример) Не печатается, как показано ниже. (Перед подсчетом обоих 200)

$ [20304 producer (3) ] До подсчета: 200, после подсчета: 203

$ [20355 корректор (2) ] До подсчета: 200, после подсчета: 201

Теперь есть две проблемы.

Во-первых, код не заканчивается. Для завершения можно ввести только ^C .

Во-вторых, ‘item_count’ кода всегда должен быть не менее 1 и иметь значение меньше 10. Но иногда оно выходит за рамки этого значения. Я думаю, иногда кажется, что потоки не работают атомарно. Таким образом, возникает ошибка. Когда я запускаю код, который я написал ниже, ошибок может не быть, но большинство ошибок возникает. Я хочу, чтобы вы сказали мне, почему.

 #include <sys/time.h>
#include <stdio.h>
#include <pthread.h> 
#include <errno.h>

pthread_mutex_t region_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t space_available = PTHREAD_COND_INITIALIZER;
pthread_cond_t data_available = PTHREAD_COND_INITIALIZER;

pthread_t   tid;
int item_count = 0;
int time_count = 0;
main()
{
    pthread_t producer_thread2;
    pthread_t producer_thread3;
    pthread_t consumer_thread1;
    pthread_t consumer_thread2;
    pthread_t consumer_thread3;
    void* producer2();
    void* producer3();
    void* consumer1();
    void* consumer2();
    void* consumer3();

    pthread_create(amp;producer_thread2, NULL, producer2, NULL);
    pthread_create(amp;producer_thread3, NULL, producer3, NULL);
    pthread_create(amp;consumer_thread1, NULL, consumer1, NULL);
    pthread_create(amp;consumer_thread2, NULL, consumer2, NULL);
    pthread_create(amp;consumer_thread3, NULL, consumer3, NULL);
    pthread_join(producer_thread2, NULL);
    pthread_join(producer_thread3, NULL);
    pthread_join(consumer_thread1, NULL);
    pthread_join(consumer_thread2, NULL);
    pthread_join(consumer_thread3, NULL);
}

void add_buffer(int i) {
    tid = pthread_self();
    if(item_count   i >= 10)
        printf("error producer(%d)n",i);
    else
        item_count = item_count   i;
    sleep(1);
    time_count  ;
    printf("time: %dn",time_count);
    printf("[%d producer(%d)] Before count: %d, After count: %dn", (int)tid, i, item_count - i, item_count);
}

void sub_buffer(int i) {
    tid = pthread_self();
    if(item_count - i <= 0)
        printf("error consumer(%d)n",i);
    else
        item_count = item_count - i;
    sleep(1);
    time_count  ;
    printf("time: %dn",time_count);
    printf("[%d consumer(%d)] Before count: %d, After count: %dn", (int)tid, i, item_count   i, item_count);
}

void* producer2()
{
    while (1) {
        pthread_mutex_lock(amp;region_mutex);
        if(item_count   2 >= 10) {
            pthread_cond_wait(amp;space_available, amp;region_mutex);
        }
        add_buffer(2);
        if (time_count == 60)
            break;
        pthread_cond_broadcast(amp;data_available);
        pthread_mutex_unlock(amp;region_mutex);
    }
    pthread_exit(NULL);
}

void* producer3()
{
    while (1) {
        pthread_mutex_lock(amp;region_mutex);
        if(item_count   3 >= 10) {
            pthread_cond_wait(amp;space_available, amp;region_mutex);
        }
        add_buffer(3);
        if (time_count == 60)
            break;
        pthread_cond_broadcast(amp;data_available);
        pthread_mutex_unlock(amp;region_mutex);

    }
    pthread_exit(NULL);
}

void* consumer1()
{
    while (1) {
        pthread_mutex_lock(amp;region_mutex);
        if (item_count - 1 <= 0) {
            pthread_cond_wait(amp;data_available, amp;region_mutex);
        }
        sub_buffer(1);
        if (time_count == 60)
            break;
        pthread_cond_broadcast(amp;space_available);
        pthread_mutex_unlock(amp;region_mutex);
    }
    pthread_exit(NULL);
}
void* consumer2()
{
    while (1) {
        pthread_mutex_lock(amp;region_mutex);
        if (item_count - 2 <= 0) {
            pthread_cond_wait(amp;data_available, amp;region_mutex);
        }
        sub_buffer(2);
        if (time_count == 60)
            break;
        pthread_cond_broadcast(amp;space_available);
        pthread_mutex_unlock(amp;region_mutex);
    }
    pthread_exit(NULL);
}
void* consumer3()
{
    while (1) {
        pthread_mutex_lock(amp;region_mutex);
        if (item_count - 3 <= 0) {
            pthread_cond_wait(amp;data_available, amp;region_mutex);
        }
        sub_buffer(3);
        if (time_count == 60)
            break;
        pthread_cond_broadcast(amp;space_available);
        pthread_mutex_unlock(amp;region_mutex);
    }
    pthread_exit(NULL);
}
 

Комментарии:

1. вы выходите из потоков через «break» без разблокировки мьютекса. Вероятно, поэтому он не завершается.

2. Вы также неправильно используете свои переменные условий. Они не являются «состоянием»; это механизм сигнализации ; вот и все . Вы должны управлять состоянием с помощью внешних данных предикатов, что в первую очередь является реальной причиной мьютекса (для защиты данных предикатов). Ваш код вообще не защищает от ложных пробуждений, особенно при всех этих трансляциях.

3. Тогда что я должен сделать, чтобы действительно защитить его?

4. Я предлагаю вам начать с одной пары потребитель / производитель и сначала разобраться с этим.