Задача Эдсгера Дейкстры о философах – великая задача великого программиста. Уж сколько лет, а она актуальна. Решая ее, прикасаешься к этому величию. И вот, перефразируя известное, «давно не было такого и вот опять», можно познакомиться с ее «новым прочтением» на Хабре[1].

Ну, как новое?… Но она стала тем триггером, который подвигнул меня к очередной попытке ее решения. Тем более, что с момента знакомства с философами пролетела уйма лет, а в  багаже - опыт применения автоматной модели и значительно усовершенствованная среда их реализации.

Познакомился с проблемой обедающих философов – Dinning Philosopher Problem (DPP), я более двадцати лет тому назад (про DPP см. [2]). Результатом стала статья, в которой философы выполняли поставленную задачу, как минимум, не хуже, чем классические алгоритмы сортировок[3]. Позднее был сделан доклад на конференции по параллельным вычислениям в Саратове, где на суд научной общественности была предъявлена модель автоматных параллельных вычислений и пример ее приложения - задача Дейкстры[4].  

Замечание 1. В рамках обсуждения статьи на Хабре было проигнорировано  предложение поручить сортировку философам. Зря, конечно, т.к. надо же как-то убедиться, что предлагаемое решение работает хотя бы в первом приближении. К примеру, тот же DeepSeek, моментально выдавший свое решение DPP, так и не смог заставить их сортировать.

Не знаю, считается ли данная задача решенной, но то, с чем я знаком, по большей части беглое рассмотрение проблем, которые она отражает. У задачи есть теория, которая представлена монографией Хоара[5], или моделями сетей Петри у Питерсона[6] и В.Е. Котова[7] или другими подобными публикациям. Но, повторюсь, все это по большей части достаточно краткий анализ свойств модели и/или даже конкретного решения. Статья на Хабре из этой же серии. Все это ни как не окончательное решение описываемых ею проблем параллелизма. Правда, может, [авторами] вопрос так и не ставился, но все же ответ на него весьма желательно иметь.

Сейчас меня не устраивает и мое давнее  решение (см. также [8]). А поскольку в моих руках имеется значительно усовершенствованные за прошедшее время средства, формальные – автоматная параллельная модель и инструментальные – среда ВКПа, то еще одна попытка подступиться к ее решению не представляется такой уж бессмысленной. А тут еще такой «мотивационный случай» – статья на Хабре!

О моем самом свежем решении проблем обедающих философов и пойдет далее речь.

Модель «философа на вилке»

Немного повозившись (больше времени ушло на адаптацию давнего решения к ВКПа), удалось создать более простую модель, которая показана на рис. 1.  В соответствии с классикой она состоит из моделей философа и вилки. Реализация на С++ в ВКПа и последующее тестирование подтвердили ее правильность. Мы ее подробно рассматривать не будем, а перейдем к более простой, но эквивалентной ей однокомпонентной модели. 

Такая модель была создана экспериментальным путем. Для этого в пошаговом режиме работы среды ВКПа отслеживались текущие состояния двухкомпонентной модели, которым ставились в соответствие состояния однокомпонентной модели. По ходу были определены предикаты и действия на переходах между ними.  Заметим, что они при этом остались неизменными, т.к. формально мы лишь заменили управление программы.

Говоря другими словами, мы нашли композицию автоматов, которая находится путем операции  умножения автоматов. Мы упростили себе задачу подобно тому, как калькулятор упрощает операцию умножения чисел. Здесь таким калькулятором стала среда ВКПа. Хотя делать подобные вещи нужно формальным путем или, действительно, на специализированном калькуляторе, а не «на глазок».

Рис. 1. Двухкомпонентная модель философа
Рис. 1. Двухкомпонентная модель философа

Созданный однокомпонентный автомат показан на рис. 2. Именно эту модель далее мы будем называть «философ на вилке».  Имена состояний модели составлены из имен состояний исходной модели, когда, например, состоянию с именем «wf» соответствуют состояния компонентных автоматов «w» и «f» (см. рис. 1).

Рис. 2. Однокомпонентная модель философа, эквивалентная модели на рис. 1.
Рис. 2. Однокомпонентная модель философа, эквивалентная модели на рис. 1.

От размышлений к еде

Размышлениями и разговорами сыт не будешь. Как ни крути, а есть когда-то да захочется.  Чтобы понять когда, рассмотрим подробнее предикаты и действия модели. Предикаты x2 и x3 принимают истинное значение, если философы слева и справа находятся соответственно в состояниях «wo» и «eo» (напомним, что соседи – это такие же автоматы). В состояние «eo» автомат попадает, когда философ желает приступить к еде и его вилка не занята. Так он фиксирует свою вилку. В состоянии «wo» философ находится, когда размышляет. Вилка в этот момент ему не нужна, и если его сосед слева в какой-то момент решит перекусить, то переходом в это состояние философ разрешает ему ее взять.

Рассмотрим поведение философа в состоянии «eo».  Здесь философ хочет кушать, но вилка соседа справа может быть занята. Чтобы ожидание не перешло в голодание, нормальный философ немного подождет, например, посчитав число тактов «голодания». А когда они превысят заданное число, он добровольно откажется от еды, возвратившись в состояние «размышления» - «wf». А тут ему, действительно, будет, о чем подумать! Голод, что ни говори, не тетка!

Цикл в состоянии «eo»  исключает ситуацию тупика. Дополнительно при завершении этого цикла философ в действии y4 устанавливает новое максимальное значение  цикла ожидания. Так мы исключаем другую тупиковую ситуацию – коллективного голодания, т.е. синхронного попадания множества философов в состояние голода. В этом случае, когда они в следующий момент вдруг опять одновременно попрутся есть, то откажутся от еды уже в разное время. Тем самым, их поведение разнообразится и подобная ситуация в последующем не возникнет.

Замечание 2. Может показаться, что «смерть от голода» грозит философу и в состоянии «wo». Например, сосед справа застрянет в состоянии «eo» (обжора!?). Т.е., другими словами, как быть с викой, которую сосед не возвращает? Однако здесь такого быть не может. Философ справа переходит в «eo», имея свою вилку, и ему нужна только вилка соседа. А тот ее даст обязательно, перейдя в состоянии «wo». Это выведет соседа справа из состояния «eo», что в свою очередь переведет философа в состояние «wf». И «вилки целы и философы сыты»!

Теперь рассмотрим сортировку данных (процесс еды). На рис. 3 показан момент запуска действия y1, сортирующего вилки. Условием его запуска является нахождение текущего автомата в состоянии «eo», а соседа справа - в «wo».  В этот момент вилки в наличии и тут «промедление смерти подобно» - срабатывает переход, запуская действие y1!

В процессе тестирования, если сортировка вилок выполняется, фон диалога философа изменяется на короткое время на зеленый цвет, если же так уж случилось, что они отсортированы – то желтым, а в режиме голодания - синим (см. Gif 1).

Рис. 3. Ситуация запуска действия y1 (сортировка).
Рис. 3. Ситуация запуска действия y1 (сортировка).
Gif 1. Синхронизация философов
Gif 1. Синхронизация философов

Стратегии кормления философа

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

Были созданы три варианта, когда предикат x6 принимает истинное значение. В первом случае философ приступает к еде, когда сосед справа размышляет. Во втором он приступает к еде, когда его номер совпадает со случайным числом. Это не исключает, что одновременно захотят кушать соседи, но мы на это пошли осознанно (посмотрим, как они из этого выкрутятся). Третья стратегия - интеллектуальная. Философ приступает к еде, когда его сосед справа размышляет и требуется сортировка вилок.

Результаты тестирования на наборе чисел 1, 5, 4, 16, 66  мы свели в таблицу (табл. 1). Дискретное время автоматного пространства (автоматной сети) в котором находились философы – 10 мсек. Можно видеть, что дискретное время выдерживает достаточно строго. Его можно было бы вычислить, поделив время сортировки на число шагов. Однако, если бы мы задали дискретное время 1 мсек, то это соответствие было бы нарушено. Например, при тестировании 1-й вариант при количестве шагов – 307 затратил на сортировку 0.421 сек.


Номер варианта

Время (сек)

шагов

Пересылок

Right

3.140

313

9

rand

0.410

40

9

sort

0.102

9

3

Табл. 1. Тест философов (дискретное время – 10 мсек)

То, что время разное  от запуска к запуску, зависит от множества факторов - работы приложения и среды, в которой тест работает. Очень большое влияние на скорость и его стабильность оказывает графика и диалоги. Если их закрыть, то время даже при 1 мсек будет соответствовать числу шагов. В эксперименте для 301 шага получилось 0.301 сек.  Время сортировки можно еще уменьшить, выбрав асинхронный режим работы автоматного пространства. В этом случае время работы стало меньше 0.1 сек, т.е. ускорилось еще в три раза.

Но скорость сортировки станет совсем фантастической, если реализовать модель философов вне среды ВКПа. Как проверено, на том же массиве данных она будет в пределах 0.001 сек.  При этом, правда, придется пожертвовать возможностями визуального проектирования автоматов и моделью параллельных автоматных вычислений. Оно вам надо? Мне – нет. Но если потребуется, то выход, как вы понимаете, есть. Только я бы в таком случае разработку делал (и делаю) в ВКПа, а саму реализацию – по максимально быстрому варианту. Например, разработка приложений для микроконтроллеров, которые достаточно ограничены, часто идет именно по такому сценарию. Благо, что он уже проработан[9].

Философы на конвейере

Отталкиваясь от прошлого опыта, не грех опробовать другие варианты алгоритмов для философов. Предположим, это будет работа на конвейере. В таком случае они не гуляют, а сидят на рабочих местах и приступают к еде/сортировке по очереди.  В этом случае не будет конфликтов с ресурсами/вилками, а работа будет выполняться предположительно быстрее.  По сути, так мы реализуем четно-нечетной параллельной сортировки.

Модель философа на конвейере показана на рис. 4.

Рис. 4. Модель работника на конвейере
Рис. 4. Модель работника на конвейере

Поневоле вызывает вопросы довольно «тупая» поочередная работа объектов. Сделаем поведение работника более адекватным, запуская сортировку (см. на графе действия y3 и y4) только тогда, когда это необходимо, а в остальные моменты пусть философ отдыхает (хотя и изменяет свое текущее состояние). Для этого дополним автомат все тем же предикатом x6, который будет проверять необходимость сортировки данных. Измененная модель показана на рис. 5.

Рис. 5. Измененная модель работника конвейера
Рис. 5. Измененная модель работника конвейера

Что это нам дает? Во-первых, выполняются только необходимые действия, а потому нагрузка на процессор меньше. Он используется еще эффективнее, когда отключена визуализация работы, которая тормозит программу буквально в разы. Проверим это, создав такую же таблицу, как и выше для обычных философов.

Что мы видим? Первый вариант выполняет сортировку за 5 шагов, делая три пересылки (сортировки) данных и девять «пустых действий». Последние – это действия на переходах между «P1» и «P2», которые не выполняют полезных действий. Второй вариант тратит много больше шагов – 62, пересылок данных  - 9 и 19 пустых действий. Но самый эффективный - «умный». Здесь меньше всего шагов, всего три пересылки данных и нет «пустых действий». Потому-то и время работы у него меньше всех. А если мы закроем диалоги и графику, то время упадет до 0.02 сек. Это медленнее всего в два раза самого быстрого варианта философов (без ВКПа).

Номер варианта

Время (сек)

шагов

пересылок

пустых действий

Right

0.060

5

3

9

Rand

0.381

37

9

7

Sort

0.052

3

3

0

Табл. 2. Тест конвейера (дискретное время – 10 мс)

Почему автоматы, а не потоки?

А почему не потоки? Есть ли доказательства, что без потоков параллельное программирование невозможно? Мне они не попадались. Но есть практика тотального многопоточного программирования, убеждающая многих, что без многопоточности - ни куда. И что будет думать простой программист, которого «с пеленок» закармливают потоками, мьютексами, семафорами, гонками, тупиками и еще много-много чем? И пусть говорят, что многопоточность – это сложно и не очень хорошо и если вас не приставили к стенке, то лучше ее избегать. Но других-то вариантов не предлагают?! Бывает, конечно, что-то и предложат, но это «что-то» легко тонет в болоте многопоточности.

Полная безысходность? Возможно. Но кому-то это даже выгодно. Попробуйте разобраться в том, что другим понять не под силу? Это, как о квантовых компьютерах. Они, вроде, есть, их иногда даже демонстрируют, но их смысл и работу толком объяснить не могут. Но, ведь, легкой жизни в параллельном программировании никто не обещал. Не так ли?

С другой стороны, есть сонм научной литературы, где параллелизм существует без многопоточности. Возьмем тех же упомянутых -  Хоара, Питерсона или Котова. Но тут другая проблема. Каким боком «прилепить» подобную теорию к практике? Много ли вы знаете тех, кто использует сети Петри? Что-то слабо в это верится. Точнее не верится совсем. Многопоточность, как тараканы, проникла во все языки программирования, а вот о нативной поддержке сетей Петри я что-то не слыхивал. Я точно знаю, что, например, в стандарте С++ этого нет. А вот потоки есть!

Но есть технология программирования, которая легко обходится без многопоточности, а самое главное без ее глубинных артефактов. Она разрешает естественным образом проблемы гонок и тупиков. Выше вы с ней познакомились. А вы о ней не знали? Ну, конечно, откуда, если о ней не расскажут ни в школе, ни в институте, ни даже в научных журналах или на конференциях (разве только здесь на Хабре)? А если и расскажут, то только для того, чтобы сообщить насколько потоки лучше? Соврут, конечно, но кто в этом потом покается?

Тем не менее, «какие Ваши доказательства»? Выше мы продемонстрировали возможности автоматов на примере классической параллельной задачи. Это же можно продемонстрировать и на примере любой другой. Мы же сейчас докажем, что потоки, мютексы и т.п. вещи противоречат здравому смыслу именно с формальной, научной точки зрения. Одновременно покажем, чем их можно заменить. Возможно, кто-то придерется к строгости доказательства, но только пусть сначала его опровергнет…

Будет совсем не сложно и достаточно кратко. Нужна, правда, небольшая подготовка, чтобы понять его смысл, но это уже проблемы иного рода. Мы в основу положим достаточно известные и, главное, научно доказанные факты. Подчеркнем, уже доказанные и уже известные весьма широко! Это важно. Если они вам не известны, то есть повод, чтобы этот пробел устранить.

Итак, первое. Нет алгоритма, который нельзя было бы представить в форме программы машины Тьюринга (МТ). Таким образом, поведение любой программы общем случае может быть описано МТ. Мы не погрешим, если будем считать, что программы и алгоритмы это одно и то же.  Таким образом, любой программе (любой!) можно поставить в соответствие эквивалентную МТ.

Второе. Достаточно просто показать, что любой МТ можно поставить в соответствие эквивалентный конечный автомат[10]. При этом, несмотря на конечность числа состояний, их может быть любое число. Главный вывод, вместо МТ мы без потери общности можем рассматривать конечные автоматы (КА).

Третье. Из теории автоматов известно, что любой автомат можно разложить на множество параллельных автоматов, используя операцию декомпозиции автомата по операции умножения (см. алгебру автоматов [11]). Каждый компонентный автомат такого разбиения представляет отдельный параллельный процесс. При этом, для синхронизации автоматам не нужны мьютексы, семафоры и другие подобные механизмы. В этом случае достаточно механизма доступа к состоянию автомата. А когда текущие состояния автоматов составят нужную комбинацию (она должна соответствовать тому или иному состоянию исходного однокомпонентного автомата), то это и будет моментом синхронизации поцессов. Затем определяется переход к новой комбинации текущих состояний и далее все повторяется.

Вот и все доказательство! Как Вам такое, Илон Маск?!

А какова перспектива автоматных вычислений? Не забудут ли их, как это фактически уже случилось с сетями Петри? Действительно, был период, когда автоматы задвинули на задворки истории, посчитав, что они исчерпали свои возможности. Именно с точки зрения параллелизма. Примечательно, что в это же время был наиболее активный интерес к сетям Петри. Но где теперь сети Петри, а где автоматы?

Не будем загадывать, но в настоящее время происходит расширение областей применения автоматов. Налицо буквально «автоматный ренессанс» (см. хотя бы [12]). Это достаточно очевидно и при этом их возможности далеко не исчерпаны. Мой опыт в среде ВКПа это только подтверждает.

Что есть у автоматов, но нет у потоков.

Строго говоря, у потоков нет  алгоритмической модели. Есть интуитивное понятие потока и не более того. А много потоков – вот и многопоточность. Запредельный уровень фантазии. Но вот как считать и что считать – тут можно фантазировать. Программисты и фантазируют. За алгоритмическую модель взяли существующую модель блок-схем. Явно сильно не напрягались, т.к. взяли то, что лежит под ногами.  Справедливости ради нужно признать, что выбора особого у них не было: все основные языки программирования и новые, и сильно старые, и совсем уж убогие стандартно реализуют именно эту модель.  Тут не разгуляешься. Есть конечно другие языки – функциональные, логические… Но на мой взгляд это уже запредельный уровень фантазии.

Святое – взять то, что уже есть. И в этом есть свой плюс. Ведь, моделью вычислений потока (или в потоке?) может быть и автомат?  Почему бы и нет? Например, есть асинхронные сети автоматов. Они идеологически вполне подходят, но … стоп! Давайте не будем измываться над автоматами, а вернемся к потокам.

Итак, есть потоки, а в них – блок-схемы. Заметим, реализуемые на любом языке программирования – Си, С++, Phyton, Go и далее по списку. Множество параллельных блок-схем – формальная модель многопоточности. Но есть одна большая проблема – аппаратная. Много потоков не организуешь даже при наличии большого числа ядер. Потоков, а тем более ядер, как и денег, всегда не хватает. Нужно … майнить. Тьфу, - имитировать.

Потоки моделируют программно. Для этого время от времени текущий поток прерывается, а управление, т.е. ресурс процессора, передается другому потоку. Для этого создали, а, скорее, даже использовали, систему прерываний. И так по кругу. С этого, кстати, начали во времена, когда было всего одно ядро. Боже, было ж, ведь, когда-то такое время или забыли?

Но, используя прерывания, с размаху «дали в штангу», т.к. не подумали об условиях и/или моментах порождения прерываний. Пошли по самому испытанному и простому пути – разрешили прерывать тогда, когда вздумается.  Достаточно быстро выяснилось, что это не хорошо, но… дело-то сделано. И тут, не придумав кардинального решения проблемы (а, кстати, как это - кардинально?), пошли другим путем – перевели стрелки на программистов.

Программисты же в свою очередь не придумали ни чего лучшего для решения «проблемы бардака прерываний», как ввести атомарные переменные, мьютексы, семафоры и что-то там еще.  В результате «бардак» чуть уменьшили, но добавились другие проблемы. Вот с этим мы и живем до сих пор, когда лучшим решением является совет - не использовать многопоточность, когда можно «не стрелять себе в ногу» (так и хочется сказать - в голову).

Не мне бы давать советы [конкурентам], но все же можно было бы заложить хотя бы атомарность в систему прерываний? Не на уровне, конечно, ассемблерных команд (их, кажется, не прерывают?), но хотя бы довести дело до уровня операторов языка программирования, а лучше сразу - функций. Спросите – как?  Здесь могут быть разные варианты, но в любом случае это повысило бы надежность программирования, уменьшило бы количество проблем. Или, может, это уже сделано?

А что автоматы? Здесь (в ВКПа) атомарность доведена до уровня такта дискретного времени. В его пределах прерываний  нет.  Но, правда, есть нюансы. В пределах такта сначала выполняются все предикаты, а только потом все действия. А измененные значения памяти сначала фиксируются в теневой памяти и лишь после выполнения всех действий, но до начала следующего такта, становятся истинными значениями переменных. В первую очередь это актуально для выходных переменных автомата. К локальным переменным автомата такое правило может не применяться (но подробнее см. [13]).

Но даже здесь могут быть отклонения. Философы это демонстрируют. В борьбе за ресурсы «тормозить» негоже. Это демонстрирует переменная, которая разрешает философу приступать к еде. Она, хотя и внешняя, работает по принципу обычной переменной – устанавливается сразу после изменения (занятия ресурса). В ВКПа есть и такая возможность. Нарушение принципов модели? Нет, конечно.  Мы здесь так делаем, чтобы упростить доступ к ресурсу. И это нормально. Принципиальность тоже имеет свои границы.

Все описанное выше – это требования вычислительной автоматной модели. Именно они обеспечивают корректность модели параллельных вычислений, делают ее простой и надежной. Вот этого у потоков нет и близко.  Оттого у них такой «бардак», когда единственно надежный совет – не использовать потоки. Хотя что-то из качеств автоматной модели можно было бы перенести и в потоки, чтобы сделать их хотя бы  предсказуемыми. Но о таких попытках слышать не довелось.  

 Выводы

Представленное в работе решение задачи Дейкстры не базируется на потоках. В нем нет ни мьютексов, ни семафоров. Сама модель философа проста, наглядна и у нее есть теория. Они не голодают, не попадают в тупики, могут сколь угодно гулять и свободно выбирать время, чтобы сытно поесть. Что еще надо для спокойной и счастливой жизни? Вот вам и практические доказательства параллелизма вне многопоточности.

Задача о философах демонстрирует проблемы доступа к общему ресурсу. Созданное решение показывает, что это можно сделать весьма просто – используя, с одной стороны, переменную обычного типа, управляющую доступом к ресурсу, а, с другой стороны, используя  синхронизацию процессов на базе состояний, чтобы корректно запустить операцию доступа к  ресурсу.   

Безусловно, сортировка не тест, которому можно доверять на все «сто», но… DepSeek, выложивший моментально свое решение, когда я попросил на его базе создать сортировку, до сих пор эту проблему так и не решил. Хотя, если честно, я и не сильно настаивал. Почему? - это отдельный разговор и пример того, что создать код – это одно, а сделать его рабочим – другое. Я же просто озвучиваю то, что  получилось из моих бесед с ИИ.

Часто спрашивают про эффективность автоматов в сравнении с потоками. Алгоритм параллельной четно-нечетной сортировки, созданный DeepSeek, на том же наборе данных затратил 0.03 сек и более. Его автоматный аналог – философы на конвейере – 0.02 сек. Не намного, но меньше. И это в режиме интерпретации автоматов и с диалогами. Но есть, ведь, еще и самое шустрое решение!

Литература

1.       Обедающие философы на Go: как не умереть от взаимной блокировки и голодания. https://habr.com/ru/articles/951224/

2.       Application Note Dining Philosophers Problem (DPP) Example. https://www.state-machine.com/doc/AN_DPP.pdf

3.       Параллельные сортировки: быстрее, проще... умнее. https://www.osp.ru/os/2004/05/184293

4.       ВЫСОКОПРОИЗВОДИТЕЛЬНЫЕ ПАРАЛЛЕЛЬНЫЕ ВЫЧИСЛЕНИЯ НА КЛАСТЕРНЫХ СИСТЕМАХ
Самара, 30 сентября – 02 октября 2004 года. https://elibrary.ru/item.asp?edn=tisrrp

5.       Хоар Ч. Взаимодействующие последовательные процессы: Пер. с англ. – М.: Мир, 1989. 264 с.

6.       Питерсон Дж. Теория сетей Петри и моделирование систем: Пер с англ. – М.: Мир, 1984. – 264с.

7.       Элементы параллельного программирования/В.А. Вальковский, В.Е. Котов, А.Г. Марчук, Н.Н. Миренков; Под ред. В.Е. Котова. – М.: Радио и связь, 1983. – 240с.

8.       Обедающие философы Дейкстры (о модели параллельных процессов). http://www.softcraft.ru/auto/ka/fil/

9.       Как избежать кошмара параллелизма в IoT: автоматы вместо потоков и корутин. https://habr.com/ru/articles/937448/

10.   Машина Тьюринга, как модель автоматных программ. https://habr.com/ru/articles/481998/

11.   Мелихов А.Н. Ориентированные графы и конечные автоматы. – М.: Наука, 1971. – 416 с.

12.   Визуальное проектирование управляющей логики фитнес-браслета. https://habr.com/ru/companies/etmc_exponenta/articles/910114/

13.   Автоматное программирование: определение, модель, реализация. https://habr.com/ru/articles/682422/

Комментарии (15)


  1. eao197
    22.11.2025 07:22

    Есть ли доказательства, что без потоков параллельное программирование невозможно? Мне они не попадались.

    Знаете, это уже за гранью добра и зла. Вы как будто намеренно демонстрируете собственную необучаемость. Вам в комментариях к вашим статьям уже неоднократно говорили, что само по себе "параллельное программирование" возникает только когда код реально исполняется параллельно на параллельно работающих ядрах CPU. А современные ОС распределяют по ядрам именно что потоки/треды (threads). Даже если вы свое приложение разбиваете на N однопоточных процессов, все равно единицей диспетчеризации для ОС является поток/тред.

    Так что без параллельно работающих потоков (пусть даже в вырожденном виде из N однопоточных процессов) у вас не будет параллельного программирования по определению.

    Но других-то вариантов не предлагают?!

    Еще как предлагают.

    Бывает, конечно, что-то и предложат, но это «что-то» легко тонет в болоте многопоточности.

    Ничего не тонет. Вот, к примеру, несколько вариантов реализации задачи обедающих философов на базе многопоточности, в которой пользователю не нужно иметь дела ни с mutex-ами, ни с atomic-ами, ни с condition_variable: тыц. И это все было описано здесь на Хабре еще до того, как вы начали публикать свои трудночитаемые и написанные псевдонаучным языком статьи с росказнями о том, как избавиться от ужасов параллельного программирования путем оказа от самого праллельного программирования.


    1. lws0954 Автор
      22.11.2025 07:22

      Здравствуйте! Я искренне рад Вас слышать.

      Но Вы, как мне представляете, не очень меня понимаете.

      Ну, первое. Я совсем не против потоков. А на аппаратном уровне - так даже за. Но я против засилья многопоточности (потоки и многопоточность, строго говоря это разные вещи), у которой, скажем так, слабая теоретическая база. Фактически ее нет. Я, например, что-то не припоминаю, чтобы где-то серьезно рассматривалась параллельная модель, состоящая из множества параллельных блок-схем. Можно было-бы ее назвать - сеть БС. Возможно, я не прав. Но даже, если бы где-то и рассматривалась, то я ее скорее бы просто ее проигнорировал.

      Безусловно, в определенном смысле я необучаемый, т.к. обучаться тому, во что я абсолютно не верю, - зачем? Какая польза от этого? В статье же я даже представил доказательство, почему моя вера обоснована. Все строго, все научно. Или в моем доказательстве есть пробелы, ошибка? Есть или нет? Уж Вы-то должны в этом разбираться. Если что-то не так, то подскажите. Я только скажу спасибо и, возможно, начну штудировать, обучаться какой-нибудь другой теории. Но какой? Посоветуйте, подскажите.

      Теперь о DPP. Я просмотрел Вашу статью. Интересно, конечно, но по мне как-то сложновато. Ну, это может в силу моей необучаемости :). Но Я обратил внимание на протоколы работы философов. Вы, как автор кода, можете ли и своих философов попросить пересортировать вилки и опубликовать протокол их работы? Было бы поучительно посмотреть.


      1. eao197
        22.11.2025 07:22

        В статье же я даже представил доказательство, почему моя вера обоснована.

        Доказательство обоснованности веры? Это какой-то оксюморон. Либо доказательства, либо вера. Вы уж определитесь.

        Все строго, все научно.

        Нудно, трудночитаемо и с закосом под наукообразие -- может быть.

        Вы, как автор кода, можете ли и своих философов попросить пересортировать вилки и опубликовать протокол их работы?

        Вы, мягко говоря, ничего не поняли. А учить вас -- только портить.


        1. lws0954 Автор
          22.11.2025 07:22

          Доказательство обоснованности веры?

          Тут даже с Вами соглашусь. И даже скажу спасибо. Определился. Поскольку опровержений нет, то, безусловно, моя вера, благодаря Вам, стала обоснованной научной теорией :)

          Ну, и с философами, похоже, что-то у Вас не ладится. Какие-то они у Вас непокорные. Простую сортировку не могут осилить. А так, конечно, по "вере" хотелось бы сравнить. И так теория стала только "крепшее" ;).


          1. eao197
            22.11.2025 07:22

            С попытками в юмор у вас еще хуже, чем с попытками в код и в наукообразные статьи.


  1. GidraVydra
    22.11.2025 07:22

    Есть ли доказательства, что без потоков параллельное программирование невозможно? Мне они не попадались.

    Вы хотите доказательство определения?


    1. lws0954 Автор
      22.11.2025 07:22

      Таки давайте, посмотрим.


    1. vadimr
      22.11.2025 07:22

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


      1. lws0954 Автор
        22.11.2025 07:22

        У меня есть вариант, но прежде хотелось бы знать что Вы считаете потоком. Только одно условие - определение не должно быть привязано к железу.


        1. vadimr
          22.11.2025 07:22

          Я считаю, что это спор о терминах.

          Сам я слово "поток" использую применительно к соответствующей структуре операционной системы или библиотеки среды программирования.


          1. lws0954 Автор
            22.11.2025 07:22

            Все же Ваше определение привязано к реализации. Пусть не железной, но программной. Я думаю, что поток лучше определять через формальное понятие алгоритма. Другими словами, поток = алгоритм, а алгоритм = поток. Т.е. поток и алгоритма - это слова синонимы. Я нашел такое определение алгоритма: "Алгоритм - это правило, сформулированное на некотором языке и определяющее процесс переработки допустимых исходных данных в искомые результаты". Разве не похоже на понятие потока?

            Алгоритмы имеют разные формы (модели). Блок-схема - поток, КА - поток, МТ - тоже поток. Короче, любое формальное определение алгоритма - это одновременно и определение потока. Пока так, если не копать глубже.


  1. woronin
    22.11.2025 07:22

    Его автоматный аналог – философы на конвейере – 0.02 сек

    А если этих философов покормить на видео карте - там запустить автоматы. То какая скорость будет тогда?


    1. lws0954 Автор
      22.11.2025 07:22

      Вопрос, конечно, интересный, но это уже специализированный вариант, а подобные вещи за рамками моих интересов, да и, если честно, компетенции тоже. Речь все же должна идти в первую очередь не о философах, а о реализации автоматов. Видимо, на тех же GPU. Вопрос, требующий отдельного изучения и реализации, похоже, тоже.


  1. AndreyDmitriev
    22.11.2025 07:22

    Достаточно просто показать, что любой МТ можно поставить в соответствие эквивалентный конечный автомат[10].

    Это очень спорное утверждение, требующее строгого и дотошного доказательства. В статье я его не увидел, честно говоря.

    Дело в том, что Тьюрингову машину как раз таки невозможно в общем случае реализовать как конечный автомат. Это связано с тем, что у машины Тьюринга неограниченная память (как бы бесконечная лента), а у конечного автомата нет внешней памяти и ограниченное число возможных состояний, на то он и конечный, он хранит только текущее состояние и переходит по входным данным.

    Я полистал статьи по ссылкам, взять хотя бы статью Шалыто, там идёт фактически распознавание лишь регулярного языка, где конечный автомат вполне применим, а ему надо было попробовать гораздо более широкий класс, называемый рекурсивно перечислимыми языками, и тут внезапно выяснится, что машина Тьюринга вполне себе справляется, а вот конечный автомат - нет.

    Если ограничить машину Тьюринга конечным количеством памяти (лентой фиксированной длины), теоретически её можно смоделировать с помощью конечного автомата, но это частный случай и в общем не относится к общей модели машины Тьюринга.


  1. checkpoint
    22.11.2025 07:22

    Помоему задача DPP решается вообще без всяких мютексов и прочей хни. Достаточно отобрать у философов право брать вилки самостоятельно, вместо этого раздавать им вилки по неоходимости (ввести в схему официанта). В такой схеме философ постоянно занимается делом (думает), но когда он захотел поесть, он должен сигнализировать об этом официанту (например открытием рта) и ждать пока ему принесут ровно две вилки. После того, как философ поел, он закрывает рот, официант забирает у него вилки и отдает другому (или не отдает вообще никому). Официант, в свою очередь, мониторит наличие свободных вилок и ведет учет очередей на "поесть". Алгоритм диспетчеризации (раздачи вилок) при этом может быть каким угодно - Round-Robin, FIFO и т.д. Такой подход позволяет решать подмножество задача с N философами и M вилками, где N и M произвольные целые числа. А также для задач где философам могут потребоваться еще и ложки, ножи и прочая столовая утварь. В таких сложных задачах использование семафоров/мютексов это прямой путь в тупик. :-)

    Собсно, это упрощенная модель по которой работают многозадачные операционные системы.