LINUX.ORG.RU

Синхронизация потоков


0

0

Задача : имеется глобальная структура , в которой есть флаг .
Для работы с этим флагом нужно создать 2 потока , каждый из которых будет выполнять отдельную функцию : первый поток - назовем его left - будет активировать этот флаг , второй - right - деактивировать .
Процесс активации-деактивации сделать поочередным в течении неопределенного промежутка времени.
Из кода понятно , что если закомментировать блокировку , то работать это не будет.
У меня вот какой вопрос : что изменится , если раскомментировать условную переменную ?
Визуально - вроде ничего , поэтому непонятно ...

★★★★★

#include    "pthread.h"

int    nthreads ;

typedef struct 
{
  pthread_t     thread_tid;     /* thread ID */
  long          thread_count;   /* #connections handled */
} Thread;
Thread  *tptr;      /* array of Thread structures; calloc'ed */


struct {
  pthread_mutex_t   mutex;
  pthread_cond_t    cond;
  int               counter; /* number ready for consumer */
} nready = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER };


void create_left_thread()
{
    void    *left_thread_main(void *);
    nthreads = 1;
    tptr = calloc(nthreads, sizeof(Thread));
    pthread_create(&tptr[0].thread_tid, NULL, &left_thread_main, (void *) 0);
    return;     

}

void create_right_thread()
{
    void    *right_thread_main(void *);
    nthreads = 1;
    tptr = calloc(nthreads, sizeof(Thread));
    pthread_create(&tptr[1].thread_tid, NULL, &right_thread_main, (void *) 1);
    return;     /* main thread returns */

}



void * left_thread_main(void *arg)
{

    int real_time = 0;

    for ( ; ; ) 
    {

            pthread_mutex_lock(&nready.mutex);
            if (nready.counter == 0)
            {
                //Pthread_cond_signal(&nready.cond);
                nready.counter++;
                printf ("left %d\n",nready.counter);
            }    
            pthread_mutex_unlock(&nready.mutex);
    }
}


void * right_thread_main(void *arg)
{

    for ( ; ; ) 
    {

        pthread_mutex_lock(&nready.mutex);
        if (nready.counter != 0)
        {
            //Pthread_cond_signal(&nready.cond);
            nready.counter--;
            printf ("right %d\n",nready.counter);
        }
        pthread_mutex_unlock(&nready.mutex);

    }

}

 
int main(int argc, char **argv)
{

    nready.counter = 0 ;

    create_left_thread();
    create_right_thread();

    for ( ; ; )
    {
        sleep(1);
    }


}

kto_tama ★★★★★
() автор топика

> У меня вот какой вопрос : что изменится , если раскомментировать условную переменную ?

Если это завуалированный вопрос "зачем нужны условные переменные, если есть mutex'ы", то ответ "чтобы избежать занятого ожидания, которое у тебя в полный рост.

P.S. код смотрел вполглаза, ибо терпеть не могу ненужных typedef.

tailgunner ★★★★★
()

conditional variable используй.

mv ★★★★★
()
Ответ на: комментарий от kto_tama

> стивенс почему-то терпел :-)

Наверно, потому что не хотел писать struct Thread* thread;

Begemoth ★★★★★
()
Ответ на: комментарий от kto_tama

Комментирование pthread_cond_signal() в твоем коде действительно ничего не меняет, потому как nready.cond больше нигде не используется (можно и от мьютексов избавиться и без interlocked/atomic обойтись). Но если оставить как есть, то один из тредов всегда будет крутиться в цикле ожидания, т.е. съест 100% CPU. Поэтому pthread_cond_wait()...

ly
()
Ответ на: комментарий от ly

Я конечно ступил : pthread_cond_signal() идет совместно с pthread_cond_wait().
Вопрос был про то , как работает эта комбинация ? Т.е. если в одном треде стоит pthread_cond_wait() , он будет стоять до тех пор , пока в другом не сработает pthread_cond_signal() ?

kto_tama ★★★★★
() автор топика
Ответ на: комментарий от ly

>то один из тредов всегда будет крутиться в цикле ожидания, т.е. съест 100% CPU

если застопарится на lock от мьютекса то CPU есть не будет.

Deleted
()
Ответ на: комментарий от kto_tama

Либо до тех пор, пока в другом треде не дадут pthread_cond_broadcast(), либо до тех пор, пока не проснётся случайно по ошибке, так что условие, о котором тебе сообщает сигнал надо проверять ещё раз.

devinull ★★
()
Ответ на: комментарий от Deleted

Ну дак в коде который он показал мьютекс сразу отпускается, поэтому получится чистый busy-loop, т.е. один тред _всегда_ будет выполняться.

ly
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.