LINUX.ORG.RU

Накатал статью по своему скромному опыту войн с потоками

 , , ,


1

1

По следам треда: Python Shared Objects

Поскольку в прошлом треде все рискнувшие пройти по ссылке заснули на половине статьи, то я решил написать статью в 3 раза короче про совсем общие принципы, лишь отдаленно относящиеся к PSO:

https://habr.com/en/post/587750/ — Многозадачность и многопоточность — распространенные заблуждения и недопонимания

★★★★
Ответ на: комментарий от byko3y

Пф-ф-ф: взять из аккаунта a 100$ и положить их в b, взять из аккаунта b 100$ и положить их в аккаунт a. Да, они взаимозависмы, и прекрасно вычисляемы при этом.

где тут две блокировки??? и где тут дедлок? у нас о чем разговор-то идет?

alysnix ★★★
()

Всего число возможных сценариев выполнения первого процесса 4^4 = 256.

Почему тут возведение в степень, а не умножение?

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

Пф-ф-ф: взять из аккаунта a 100$ и положить их в b, взять из аккаунта b 100$ и положить их в аккаунт a. Да, они взаимозависмы, и прекрасно вычисляемы при этом.

где тут две блокировки??? и где тут дедлок? у нас о чем разговор-то идет?

О том, что таких ячеек может быть миллион. Предлагаешь на всех одну блокировку брать?

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

О том, что таких ячеек может быть миллион. Предлагаешь на всех одну блокировку брать?

такое решается через установление порядка блокирования.

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

Почему тут возведение в степень, а не умножение?

4*4*4*4 — если тебе так удобнее. Четыре операции на первом шаге, для каждой из них по четыре операции на втором шаге, для каждой из 16 комбинаций по 4 возможных операции на третьем шаге, и по 4 возможных операции на четвертом шаге для каждой из возможных предыдущих 64 комбинаций.

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

На уровне реализации транзакций в БД, например.

две вложенные блокировки с возможностью дедлока, блин! где это тут???

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

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

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

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

Предлагаешь на всех одну блокировку брать?

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

но это не про дедлоки вообще. так что первые полстатьи можешь выкинуть в мусорку.

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

две вложенные блокировки с возможностью дедлока, блин! где это тут???

Вообще-то в каком-нибудь Firebird перемещение суммы в одном направлении и обратно в другом направлении приводило к дедлоку — одна из транзакций отменялась по таймауту.

тут чисто последовательные операции, блокировка там чисто техническая(просто условно говоря, кошели эти в одном файле хранятся), бэдэ-шмеде, не имеет отношения к вопросу вообще

Мне кажется, что ты сейчас нам впрашиваешь что-то уровня медиа-проигрывателя, которому нужно медиа-библиотеку обрабатывать в одном потоке, воспроизводить звук в другом потоке, а интерфейс рисовать — в третьем. То есть, это даже близко не высоконагруженная система.

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

Многозадачность и многопоточность — распространенные заблуждения и недопонимания

Не понимаю почему ты обхаял передачу сообщений между потоками с хранением и изменением единой разделяемой переменной в одном месте.

  1. Якобы узел (поток) может отказать. Ввод сообщений живучести и перезапуск потока решает этот вопрос.
  2. Якобы медленное исполнение. Поток отправил сообщение и пошёл по своим делам, а в случае блокировок от тупо греет воздух и ничего не делает. Сообщенческий подход всяко обгоняет блокировочный на многоядерных процессорах, потому что в каждый момент времени работают все ядра процессора.
  3. Тупари запутаются в блокировках с вероятностью 99 процентов, а в отправке/приёме/обработке сообщений всё просто, поэтому будет меньше человеческих ошибок в многопоточном коде.
Enthusiast ★★★
()
Ответ на: комментарий от alysnix

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

Я вот сейчас вообще не понял сути претензии. Тут два варианта: либо берешь одну блокировку и забываешь про параллельные вычисления навсегда, либо берешь детальные блокировки и выносишь себе мозг. Там большая часть статьи была для того, чтобы показать, что нужно синхронизировать только тот уровень доступа, который действительно нужен между конкретными задачами, и не больше. А это что-то вроде конкретных общие данные и одного глобального счетчика. Но именно в этой ситуации начинаются проблемы — отсюда и возникла необходимость в транзакционной памяти, да такая, что даже интель на аппаратном уровне ее реализовал в процессорах. Как ты думаешь, интель просто не шарит в программировании и не умеет в правильном порядке брать блокировки?

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

Вообще-то в каком-нибудь Firebird перемещение суммы в одном направлении и обратно в другом направлении приводило к дедлоку — одна из транзакций отменялась по таймауту.

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

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

как это изменило мир

Так, что с блокировок в БД мир перешёл на CoW xD
Шучу, никуда он не перешёл, живи с этим.

izzholtik ★★★
()

Казалось бы, уже изобрели software transactional memory, пользуйся. Нет, хотим плакать и вручную дрочить мутексы.

статью не читал, конечно

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от Enthusiast

Якобы узел (поток) может отказать. Ввод сообщений живучести и перезапуск потока решает этот вопрос

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

Якобы медленное исполнение. Поток отправил сообщение и пошёл по своим делам, а в случае блокировок от тупо греет воздух и ничего не делает. Сообщенческий подход всяко обгоняет блокировочный на многоядерных процессорах, потому что в каждый момент времени работают все ядра процессора

До тех пор, пока не возникает необходимость координации/согласованности данных. Тебе нужен ответ, чтобы принять дальнейшее решение, а ответа нету, потому что, видите ли, процесс занят «полезной работой». Если тебе нужна согласованность — это только блокировки, сериализация, разделяемое состояние. Не нужна — значит, не нужно разделяемое состояние и блокировки. Но в общем случае получить согласованность из несогласованности сложнее, чем потерять эту согласованность.

Тупари запутаются в блокировках с вероятностью 99 процентов, а в отправке/приёме/обработке сообщений всё просто, поэтому будет меньше человеческих ошибок в многопоточном коде

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

byko3y ★★★★
() автор топика
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от byko3y

интель просто не шарит в программировании и не умеет в правильном порядке брать блокировки

интель в данном случае не имеет ничего кроме аппаратной памяти, шины и каких-то там ядер… это вообще не уровень приложения, не уровень иерархии данных, мьютексов, потоков, и все такое…

если интель аппаратно делает переупорядочивание команд и спекулятивное исполнение… нам на уровне приложений тоже кинуться в переупорядочивание и спекуляции что-ли??

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

разогнать индусов

https://dev.mysql.com/doc/refman/8.0/en/innodb-deadlock-example.html

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

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

и как это изменило мир??? надо было разогнать индусов, что написали этот фаерберд

Я уверен, что блокировки постгри и оракла делают то же самое.

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

Поток отправил сообщение и пошёл по своим делам, а в случае блокировок от тупо греет воздух и ничего не делает.

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

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

а так - да. мессаги - это то, что истинно верно для многотреда.

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

Прочитай немного вон там (это оф документация по дефолтному движку MySQL),

а можно своими словами? я ж вас не посылаю читать документации.

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

Казалось бы, уже изобрели software transactional memory, пользуйся. Нет, хотим плакать и вручную дрочить мутексы

Но STM там упомянуто. Сюрприз — ваш покорный слуга знает всю индустрию сверху донизу. Правда, заработать денюжек ему это знание пока что не помогает.

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

Кто не знает или не понял еще, макакич - невменяемый шиз. Не пытайтесь с ним спорить.

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

я ж вас не посылаю читать документации

Чел, там один экран текста. Ради безграничной любви к человечеству, постарайся его осилить.

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

Казалось бы, уже изобрели software transactional memory, пользуйся. Нет, хотим плакать и вручную дрочить мутексы.

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

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

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от izzholtik

постарайся его осилить.

зачем? меня не интересует ваш sql. и обсуждаемая статья заявляет о многопоточности вообще, а не sql в частности.

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

сорь, чёт кек немношк, такая непосредственность

izzholtik ★★★
()

Когда-то давно для закрытой разработки я сам реализовывал неинтрузивное логирование на Delphi

я не думал, что тебе лет под 40

tz4678 ★★
()

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

tz4678 ★★
()
Последнее исправление: tz4678 (всего исправлений: 1)
Ответ на: комментарий от tz4678

Там уже не лицемерие, там просто некомпетентная срань, нечто между главной 4пда и ответами мейлру. Редкий фейспалм долетит до середины комментариев.

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

а так - да. мессаги - это то, что истинно верно для многотреда

Да, но при условии, что эти данные локальны для канала, то есть, их пишет только передающая сторона и читает только получающая. Если внезапно оказывается, что данные могут поплыть за время доставки сообщения (потому что потоков в системе больше двух), то имеем каноничную проблему согласования, решаемую только разделяемым состоянием. И в том числе в Go ее через разделяемое состояние и блокировки решают, там весьма богатая стандартная либа по блокировкам, как бы они не кичились своим «share by communication, not communicate by sharing» — все-таки эта фраза была скорее про «используйте разделяемое состояние только по крайней необходимости». А эта необходимость неизбежно будет.

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

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

Реализаций всевозможных очередей хоть жопой жуй.

TDrive ★★★★★
()

Если я правильно понял, ты проблему дизайна пытаешься решить реализацией. Вопрос - может таки над дизайном нужно работать, а не над костылями, подпирающих эту кривизну? Как тут с же в комментариях написали, проблемы дедлоков - проблемы дизайна. Статью вс не осилил прочитать. Мозг отказывается переваривать такой объем воды.

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

а можно своими словами? я ж вас не посылаю читать документации

У РСУБД сложные блокировки, в данном случае разделяемая блокировка на чтение и эксклюзивная блокировка на удаление. Один клиент берет разделяемую блокировку на чтение, второй берет эксклюзивную на удаление, которую не может получить, и напоследок первый клиент берет блокировку на удаление, которую не может получить, поскольку второй клиент уже застолбил за собой право на эксклюзивную блокировку. Здесь играет роль механизм приоритетов, то есть, новая операция не может вырубить старую — иначе длинные операции могут никогда не закончиться.

PS: ну то есть как бы теоретически эту ситуацию можно разрулить, но практически это безумно сложно реализовать в коде, потому что нужно анализировать всю цепочку взаимозависимых транзакций.

byko3y ★★★★
() автор топика
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от den73

любая фиксированная последовательность локов подойдет же.

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

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

Да, сайдэффектушки и необратимые операции не отменишь, это правда. Также правда, что нельзя одновременно выполнить два сайдэффекта по разным ресурсам и нельзя сделать их взаимозависимыми. Обычно сайдэффект по одному ресурсу крутится только в одном потоке, и потому каких-то проблем множественных блокировок там не возникает. Это в том числе относится к ACID СУБД, которые пишут данные на диск последовательно.

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

Проглядел очень по диагонали, может что-то и зря пишу.

Надо было ещё в два раза меньше. Вместо картинки про Erlang и «подтверждение принято» - спасибо что она на русском - можно было про двух генералов, оно как-то острее ощущается. Ещё надо было написать про принцпип двух из трёх в распределённых системах.

А так я бы вообще по-другому писал такую статью. Есть просто разные требования к параллельности и разные виды её. Например, есть государство - оно работает через очереди сообщений. Взять справку, справка действительна 10 дней - что-то типа STM (хотя я тут могу ошибаться на уровне концепций даже). Отправить письмо, получить ответ (положительный или отказ), ответ должен прийти в течение такого-то таймаута.

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

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

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

Дальше, было бы неплохо описать два вида СУБД - с пессимистичной и оптимистичной блокировками (это из моего века динозавров, сейчас ещё что-нибудь придумали), и как диспетчер разрешает клинчи в них.

А для неинтрузивного логирования можно попробовать rr.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 3)
Ответ на: комментарий от tz4678

я не думал, что тебе лет под 40

Меньше, но это не важно. Много кто не думал. Я сам не думал. Я вообще плохо думаю.

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

меня на хабропараше нет. я там и не прижился БЫ из-за их манерности. я ненавижу лицемерие

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

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

Там уже не лицемерие, там просто некомпетентная срань, нечто между главной 4пда и ответами мейлру

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

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

Ты пишешь БД? Какую?

Ну если не считать in-memory, то никакую. ПисаЛ много в прошлом, только не путать с СУБД.

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

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

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

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

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

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

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

… короче.. индусы писали небось… или читали…

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

Как тут с же в комментариях написали, проблемы дедлоков - проблемы дизайна

Да, проблемы дизайна, причем, дизайна ЯП. Давай свои варианты, как ты предлагаешь создать приложуху, которая не упадет, не дедлокнется, при этом будет многопоточная/многозадачная, и не уровня hello world. Все решения для макак идут одним путем — никаких блокировок в интерфейсе программирования (или никакой многопоточности, привет питону). Я сделал для макак Python Shared Objects, которая все дедлоки разруливает полностью автоматически, которая гарантирует отсутствие голодания — последний момент почему-то за весь тред никто не вспомнил. Взятие блокировок по порядку ведь никак не защищает от голодания.

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

Атомарная операция отправки сообщения через канал гарантирует, что либо сообщение отправлено и отправка одновременно подтверждена, либо оно не отправлено — для обеспечения этой синхронизации используется разделяемое состояние канала скрытое от программиста на Go.

это из статьи автора

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

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

афтар учи матчасть!

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