#c #linux #pthreads #mutex
#c #linux #pthreads #мьютекс
Вопрос:
Я хотел бы завершить код, который удовлетворяет приведенным ниже условиям.
- В этой программе есть переменная с именем integer item_program . Есть также потребители и производители. Производитель, потребитель, выполняется как отдельные потоки. Производитель увеличивает значение переменной item_count .Потребитель уменьшает значение переменной item_count .
- Потоками этой программы являются производители (2), производители (3), потребители (1), потребители (2) и потребители (3). Производитель (2) увеличивает значение item_count на 2. Потребитель (3) уменьшает значение item_count на 3.
- Эта программа выполняется в общей сложности 60 секунд, а значение item_count всегда больше 0 и меньше 10.
- Производители и потребители должны печатать следующий формат на консоли при увеличении или уменьшении значения item_count .
=> [количество идентификаторов потоков]: до подсчета: ?, после подсчета: ?
ex1) [20304 producer (3) ] До подсчета: 2, после подсчета: 5
пример 2) [20355 корректор (2) ] До подсчета: 5, после подсчета: 3
- Значение предшествующего подсчета предыдущего оператора вывода и предшествующего подсчета последующего оператора вывода не должны совпадать.
пример) Не печатается, как показано ниже. (Перед подсчетом обоих 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. Я предлагаю вам начать с одной пары потребитель / производитель и сначала разобраться с этим.