Страницы

Поиск по вопросам

воскресенье, 29 марта 2020 г.

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

#cpp #c #многопоточность #pthread #posix


Нужно что бы два потока параллельно печатали на экран. (Первый поток печатает числа
1,2,3...10 Второй - 100,200,300...1000). Причём вывод должен быть синхронизирован:
сначала родительский поток выводит первую строку, затем дочерний первую, затем родительский
вторую строку, затем дочерний вторую и т.д.(100,1,200,2,300,3...) Использовать нужно
мьютексы.

pthread_mutex_t mut;

void printt(int i){
   pthread_mutex_lock(&mut);
   cout<


Ответы

Ответ 1



Предупреждение: согласно POSIX данное решение даёт UB [1], хотя и, судя по всему, он работает в реализации pthreads от glibc/linux; он приведен лишь для справки/как идея и не должен использоваться. Спасибо @VTT за замечание. Для решения задачи нужно количество мьютексов равное количеству потоков. Идея в том, чтобы мьютексы захватывались разными потоками попеременно, т.е. входя в критические секции нужно захватывать свой мьютекс, а при выходе отпускать мьютекс следующего потока. Само собой, перед началом выполнения свободным должен быть отпущен только один мьютекс. В итоге получается нечто следующее: pthread_mutex_t mut1; pthread_mutex_t mut2; void printt1(int i){ pthread_mutex_lock(&mut1); cout<

Ответ 2



Функция printt печатает локальную переменную i, к которой у других потоков нет доступа, а синхронизация не ожидает завершения записи предыдущей строки другим потоком. Также полностью отсутствует обработка ошибок.

Ответ 3



Без сигналов , чтоб другой поток проснулся неудобно, придумал только сон. Вроде бы пашет. Нужна переменная для знака кому какая очередь. // g++ -pthread mutex-semaph.cpp #include # include # include pthread_mutex_t mut; int queue = 1 ; // или 2 void printt(int i, int q){ Again : pthread_mutex_lock(&mut); if(queue == q) std::cout<

Ответ 4



Сделайте разделяемую volatile переменную и mutex. Присвойте переменной 1, что означает печать будет проводить первый поток. Запустите потоки. В каждом потоке в цикле захватываете mutex и читаете значение переменной. Если значение переменной в первом потоке равно 1, то он печатает данные и присваивает переменной 2. Аналогично, второй поток производит печать если значение переменной равно 2, после чего устанавливает ее в 1. (Обратите внимание, чтение и модификация переменной защищены mutex-ом.) Затем поток в любом случае снимает блокировку и (для оптимизации эффективности) вызывает pthread_yield. Конкретно в вашем случае с внешним циклом и анализом очередности печати внутри printt() (очевидно, с целью не вытаскивать работу с mutex на уровень управления циклом) в этой функции нужно дождаться, пока общая переменная не примет нужного значения. Впрочем, хватит общих слов. Вот немного модифицированный ваш код из текста вопроса. avp@avp-ubu1:hashcode$ cat t-seq-pri.c #ifdef __cplusplus #include using namespace std; #else #define _GNU_SOURCE #include #endif #include pthread_mutex_t mut; volatile int turn; void printt(int i, int q){ int pri = 0; do { pthread_mutex_lock(&mut); if (turn == q) { #ifdef __cplusplus cout<

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

Отправить комментарий