В ф-ции main я создаю 2 потока: print_xs1 и print_xs2.
print_xs1 записывает в массив arr последовательные значения.
print_xs2 считывает этот массив и выводит их на консоль.
Потоки используют мьютекс для разделения времени захвата массива.
По идее, потоки должны выполняться последовательно, но вывод программы
наводит меня на мысль, что это не так. Результат: 4545454545 (много раз), потом 67, потом 78 (оч. много раз), хотя я ожидаю:
0123456789 (оч. много раз)... Что я неправильно делаю?Код программы:
----------------------------------------------
my_threads.c
----------------------------------------------
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>int arr[2];
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;void* print_xs1 (void* unused)
{
int i=0;
while (1)
{
pthread_mutex_lock(&mutex);
arr[0]=i;
arr[1]=i+1;
i+=2;
if (i>9) i=0;
pthread_mutex_unlock(&mutex);
}
return NULL;
}void* print_xs2 (void* unused)
{
while (1)
{
pthread_mutex_lock(&mutex);
printf("%d",arr[0]);
printf("%d",arr[1]);
pthread_mutex_unlock(&mutex);
}
return NULL;
}int main()
{
pthread_t thread_id1;
pthread_t thread_id2;pthread_create(&thread_id1, NULL, &print_xs1, NULL);
pthread_create(&thread_id2, NULL, &print_xs2, NULL);while (1)
{}
return 0;
}
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>int arr[2];
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
int array_is_full = 0;void* print_xs1 (void* unused)
{
int i=0;
while (1)
{
pthread_mutex_lock(&mutex);
if (!array_is_full)
{
arr[0]=i;
arr[1]=i+1;
i+=2;
if (i>9) i=0;
array_is_full=1;
}
pthread_mutex_unlock(&mutex);
}
return NULL;
}void* print_xs2 (void* unused)
{
while (1)
{
pthread_mutex_lock(&mutex);
if (array_is_full)
{
printf("%d",arr[0]);
printf("%d",arr[1]);
array_is_full=0;
}
pthread_mutex_unlock(&mutex);
}
return NULL;
}int main()
{
pthread_t thread_id1;
pthread_t thread_id2;pthread_create(&thread_id1, NULL, &print_xs1, NULL);
pthread_create(&thread_id2, NULL, &print_xs2, NULL);while (1)
{}
return 0;
}
Спасибо, gyn61. Я использовал указанный Вами метод, это действительно помогает - потоки синхронизируются, однако происходит это довольно странно: программа при выполнении "задумывается" секунд на 15, и только после этого выводит порцию "много раз по 0123456789" (после этого опять впадает в спячку). Кстати говоря, при использовании доп.переменной можно обойтись вовсе без мьютекса - результат будет тот же (правильный, но с тормозами). Система SuSE Linux 9.0
>Спасибо, gyn61. Я использовал указанный Вами метод, это действительно помогает - потоки
>синхронизируются, однако происходит это довольно странно: программа при выполнении "задумывается" секунд
>на 15, и только после этого выводит порцию "много раз по
>0123456789" (после этого опять впадает в спячку). Кстати говоря, при использовании
>доп.переменной можно обойтись вовсе без мьютекса - результат будет тот же
>(правильный, но с тормозами). Система SuSE Linux 9.0Попробуй так.
---------------------------------------------------
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>int arr[2];
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
int array_is_full = 0;
pthread_cond_t is_full =PTHREAD_COND_INITIALIZER;
pthread_cond_t not_full =PTHREAD_COND_INITIALIZER;void* print_xs1 (void* unused)
{
int i=0;
while (1)
{
pthread_mutex_lock(&mutex);
while (array_is_full) {
pthread_cond_wait (¬_full, &mutex);
}
arr[0]=i;
arr[1]=i+1;
i+=2;
if (i>9) i=0;
array_is_full=1;
pthread_cond_signal (&is_full);
pthread_mutex_unlock(&mutex);
}
return NULL;
}void* print_xs2 (void* unused)
{
while (1)
{
pthread_mutex_lock(&mutex);
while (!array_is_full) {
pthread_cond_wait (&is_full, &mutex);
}
printf("%d",arr[0]);
printf("%d",arr[1]);
array_is_full=0;
pthread_cond_signal (¬_full);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
........
и т.д.
--------------
Большое спасибо, Pablo. Похоже, это то, что нужно. Результат запуска программы отпишу из дома (linux-система стоит именно там).
Кстати, pthread_cond_signal (¬_full) = pthread_cond_signal (&is_full) ?
>Большое спасибо, Pablo. Похоже, это то, что нужно. Результат запуска программы отпишу
>из дома (linux-система стоит именно там).
>Кстати, pthread_cond_signal (¬_full) = pthread_cond_signal (&is_full) ?Нет, просто (& not_full) без пробела неправильно транслировалось
Хотя в таком простом примере который ты привел,
с одним потоком производителем и одним потоком потребителем,
можно обойтись только одной условной переменной,
и заменить все not_full на is_full
Попробовал с одной сигнальной переменной -
Pablo, это действительно работает! Еще раз большое спасибо :)