@alienstone

Почему не возможен синхронизованный вывод двух потоков при использовании двух мутексов?

Здравствуйте,

Возникла задача - синхронизовать вывод родительской и дочерней нитей ( их всего 2) : сначала родительская нить выводит первую строку, затем дочерняя, затем родительская вторую строку и т.д. Использовать можно только мутексы, остальные средства синхронизации запрещены. Сходу не могу доказать, почему это невозможно. Подскажите, пожалуйста.

Исходный текст задачи:

Напишите программу, которая создает нить. Используйте атрибуты по умолчанию. Родительская и вновь созданная нити должны распечатать десять строк текста. Модифицируйте программу так, чтобы вывод родительской и дочерней нитей был синхронизован: сначала родительская нить выводила первую строку, затем дочерняя, затем родительская вторую строку и т.д. Используйте мутексы.

Явные и неявные передачи управления между нитями (sleep(3C)/usleep(3C), sched_yield(3RT)) и холостые циклы разрешается использовать только на этапе инициализации.

Докажите, что данная задача не может быть решена с использованием двух мутексов без использования других средств синхронизации.


Заранее благодарен.
  • Вопрос задан
  • 1707 просмотров
Решения вопроса 1
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
https://ru.wikipedia.org/wiki/%D0%9C%D1%8C%D1%8E%D...
В каждый конкретный момент только один поток может владеть объектом, защищённым мьютексом
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@Mercury13
Программист на «си с крестами» и не только
А точно нельзя?
Я бы сделал так…

Поток 1.
мютекс2.войди
поток2.старт
повторяй 10 раз
  мютекс1.войди
  writeln
  мютекс2.выйди
поток2.дождись
мютекс2.выйди

Поток 2.
повторяй 10 раз
  мютекс2.войди
  writeln
  мютекс1.выйди

Обратите внимание, мы входим в один мютекс и выходим из другого. Проверю, отпишусь.

Единственное спорное «средство синхронизации» — в потоке 1 дождаться завершения потока 2.
Ответ написан
@Eddy_Em
Что за чушь? Для этого мьютексы и придумали. Блокируем мьютекс родителем, выводим строчку, устанавливаем некий глобальный ключ в 1, сбрасываем мьютекс, ждем, пока ключ не будет 0. В дочернем же ждем, пока ключ не будет 1, блокируем мьютекс, выводим строчку, сбрасываем ключ, разблокируем мьютекс.
Если используются не потоки (pthreads), а процессы (fork), то нужно убрать буферизацию или после каждой записи сбрасывать буферы.

См. мой ответ с двумя мьютексами в комментарии к этому ответу.
Ответ написан
Olej
@Olej
инженер, программист, преподаватель
Если вас смущает простая переменная (флаг) в ответе Японский Городовой ("Что за чушь?..." - что совершенно справедливо ;-) ), то я вам набросаю другую схему - каждый из потоков выполняет что-то подобное:
while( true ) {
   while( pthread_mutex_trylock( &mutex ) == EBUSY );
   cout << "это мя строка, ура!" << endl;
   pthread_mutex_unlock( &mutex ); 
}

Здесь то и переменных никаких нет кроме мютекса ... - компилируйте, выполняйте, насаждайтесь ;-)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы