URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 3677
[ Назад ]

Исходное сообщение
"Как заставить потоки выполняться последовательно?"

Отправлено aiboman , 03-Дек-04 12:27 
В ф-ции 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;
}


Содержание

Сообщения в этом обсуждении
"Как заставить потоки выполняться последовательно?"
Отправлено gyn61 , 03-Дек-04 12:50 
#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;
}



"Как заставить потоки выполняться последовательно?"
Отправлено aiboman , 03-Дек-04 13:21 
Спасибо, gyn61. Я использовал указанный Вами метод, это действительно помогает - потоки синхронизируются, однако происходит это довольно странно: программа при выполнении "задумывается" секунд на 15, и только после этого выводит порцию "много раз по 0123456789" (после этого опять впадает в спячку). Кстати говоря, при использовании доп.переменной можно обойтись вовсе без мьютекса - результат будет тот же (правильный, но с тормозами). Система SuSE Linux 9.0

"Как заставить потоки выполняться последовательно?"
Отправлено Pablo , 03-Дек-04 13:42 
>Спасибо, 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;
}
........
и т.д.
--------------


"Как заставить потоки выполняться последовательно?"
Отправлено aiboman , 03-Дек-04 14:21 
Большое спасибо, Pablo. Похоже, это то, что нужно. Результат запуска программы отпишу из дома (linux-система стоит именно там).
Кстати, pthread_cond_signal (¬_full) =  pthread_cond_signal (&is_full) ?

"Как заставить потоки выполняться последовательно?"
Отправлено Pablo , 03-Дек-04 15:02 
>Большое спасибо, Pablo. Похоже, это то, что нужно. Результат запуска программы отпишу
>из дома (linux-система стоит именно там).
>Кстати, pthread_cond_signal (¬_full) =  pthread_cond_signal (&is_full) ?

Нет, просто (& not_full) без пробела неправильно транслировалось

Хотя в таком простом примере который ты привел,
с одним потоком производителем и одним потоком потребителем,
можно обойтись только одной условной переменной,
и заменить все not_full на is_full  


"Как заставить потоки выполняться последовательно?"
Отправлено aiboman , 06-Дек-04 11:04 
Попробовал с одной сигнальной переменной -
Pablo, это действительно работает! Еще раз большое спасибо :)