LINUX.ORG.RU

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

 , , ,


1

1

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

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

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

★★★★

Grand Central Dispatch

Operation Queues

И аналоги «каналов» в гоу / акторов в Swift - вот такой должна быть нормальная многопоточность - через специальные безопасные многопоточные структуры и обвязки, а не в ручную шарить память и разруливать к ней доступ через всякие семафоры с барьерами - всё это уже прошлый век в большинстве сценариев, питон в этом плане застрял на уровне сишечки - сильно устарел, да и никогда там вменяемой многопоточности не было

menangen ★★★★★
()

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

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

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

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

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

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

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

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

Плюсанул тебе карму и статью. Обязательно почитаю чуть попозже, сейчас занят

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

дедлок разруливается просто некоторой иерархией операций, или их порядком

Если не существует порядка между операциями? И да, зачем мутексы, если есть порядок операций?

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

Если не существует порядка между операциями?

приведите пример.

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

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

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

И да, зачем мутексы, если есть порядок операций?

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

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

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

для дедлока тут и причин никаких нет.

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

Если не существует порядка между операциями?

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

один поток сначала захватывает ресурс «а», а другой - сначала ресурс - «b». а если б они оба захватывали сначала «a», потом «b», а отпускали в обратном порядке - то дедлока и не было бы.

упс…

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

alysnix ★★★
()

Накатал статью

А на ЛОР тупо ссылку кинул, ну как так! Вот не пойду читать тебе на зло =) И ващеее я уже который раз твержу, пишите статьи и где то публикуете публикуйте их и на ЛОРе на зло всем, глядишь добавит Максим возможность и тут нормально публиковать, а так какая разница, ведь вверху пост, внизу комменты всё уже готово. Нет лишь группировки и возможности подписаться на автора как на тег и всё и то можно свой именной тег сделать по нику и вот уже готовая платформа @maxcom нужен просто ещё просто дубль форума просто форум и тоже самое но только со статьями, даже делать ничего не надо одну галку фильтр статьи, форум и всё. Ну и картинки вставлять разрешить в посты (но только ссылками). Или тупо сделать так что-бы любой пост мог быть статьёй достаточно пометить как статью и всё и сделать просто ещё 1 трекер статьи

Статьи
Новости
Галерея
Форум
Трекер
Уведомления
Поиск
LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от alysnix

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

Таймаут актуален либо для очень кривого кода, в котором тупо не отпускают блокировки, либо в случае детальных блокировок. Ты свалился на попытке взять второй мьютекс по таймауту — дальше что? Это ветка с большой вероятностью неоттестирована, и тебе повезет, если ты не приедешь после этого в сегфолт. По-хорошему тебе нужно отпустить первую блокировку и уйти на второй круг — как это делает std::lock. Это будет сделано, если std::lock получил весь перечень блокировок, но если ты сам не знаешь, какие блокировки ты брал, потому что они неявны и находятся где-то глубоко в классах, то тебе же руками придется самому повторять выполнение кода с самой первой блокировки... Которую тебе сначала придется найти.

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

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

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

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

А на ЛОР тупо ссылку кинул, ну как так! Вот не пойду читать тебе на зло

Как на лоре вставлять таблицы и картинки?

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

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

Это еще в пошлом веке, по моему Хоар доказал.

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

Пастернака я не читал и его не осуждаю.

Для возникновения дедлока достаточно существования цикла в графе зависимостей. Не всякая задача позволяет разорвать такие циклы.

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

питон в этом плане застрял на уровне сишечки - сильно устарел

GCD/libdispatch в сишечке работает прекрасно. а так да, плюсую :)

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

Grand Central Dispatch
Operation Queues

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

https://github.com/kassergeymac/Dining-philosophers-problem

А если так, то ты получаешь обратно свою необходимость «в ручную шарить память и разруливать к ней доступ через всякие семафоры с барьерами», с GCD или без — разницы нет.

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

Для возникновения дедлока достаточно существования цикла в графе зависимостей.

покажите на примере. «цикл в графе зависимостей»… это ни о чем. о каких «зависимостях» тут речь?

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

Это еще в пошлом веке, по моему Хоар доказал.

мне это очевидно без особых доказательств.

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

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

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

А ты к одному ресурсу всегда обращаешься через единственную функцию, что ли? В статье есть элементарный пример ситуации, когда это не прокатывает: a := b + 1. Две ячейки — нужно две блокировки.

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

Это еще в пошлом веке, по моему Хоар доказал

Ну что значит «доказал»... предложил как один из вариантов, потому что семафоры Дейкстры по своему устройству дают дедлок только при разном порядке взятия — это не универсальное свойство всех механизмов синхронизации на свете.

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

Для возникновения дедлока достаточно существования цикла в графе зависимостей. Не всякая задача позволяет разорвать такие циклы

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

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

Статья из серии «Ничего обо всём»

От моей последней статьи «всё про ненужно» мозги сгорели у всех посетителей.

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

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

Порядка нет. Чтобы был порядок, независимые участники должны заранее договорится, но тогда это не независимые участники, и задача другая с другим (бес)порядком.

И да если есть порядок, то цикла нет, так как цикл как раз нарушает «отношение порядка».

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

В статье есть элементарный пример ситуации, когда это не прокатывает: a := b + 1.

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

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

Чтобы был порядок, независимые участники должны заранее договорится, но тогда это не независимые участники, и задача другая с другим (бес)порядком.
И да если есть порядок, то цикла нет, так как цикл как раз нарушает «отношение порядка»

Ну в случае спонтанно возникающих циклов — да, на обычных семафорах Дейкстры это нерешаемая задача.

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

Порядка нет.

пример давайте. пока одни словеса.

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

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

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

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

Пф-ф-ф, зачем тут вообще блокировка тогда? Без блокировки читай b и пиши в a. Смех-смехом, а есть люди, которые так делают счетчики производительности, которые часто дергаются и потому атомарные операции над ними потому дорого стоят. У меня где-то была статья с бенчами таких счетчиков, где выяснилось, что в самых запущенных ситуациях они теряют порядка 95% инкрементов.

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

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

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

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

Пф-ф-ф, зачем тут вообще блокировка тогда?

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

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

Ага, получится как в сталкере, где просто забивали на гонки,

базар про сталкера, бенчи каких-то счетчиков, тетю в чернигове и бузину в огороде кончай. по делу говори.

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

По началу ссылками и псевдографикой =)

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│                       example threads work                  │
│                                                             │
├─────────────────────────────────────────────────────────────┤
├─────────────────────────────────────────────────────────────┤
│                                                             │
│                                                             │
│   ┌─┬────────────┬─┐                    ┌────────────────┐  │
│   │ ├────────────┤ │       ┌──┐         │                │  │
│   │ │            │ │       │  │         │ ┌────────────┐ │  │
│   │ │ thread 1   │ ├─────► │  │         │ │            │ │  │
│   │ │            │ │       │  │         │ │            │ │  │
│   │ │            │ │       │  │  ◄──────┤ │  thread 2  │ │  │
│   │ └────────────┘ │       │  │         │ │            │ │  │
│   │                │       │  │         │ │            │ │  │
│   │  ┌──────────┐  │       │  │         │ └┬──────────┬┘ │  │
│   │  │          │  ├─────► │  │         │  ├──────────┤  │  │
│   │  │          │  │       │  │         │  │          │  │  │
│   │  │     t1   │  │       │  │         │  │          │  │  │
│   │  │          │  │       │  │ ◄───────┤  │    t2    │  │  │
│   │  │          │  │       │  │         │  │          │  │  │
│   │  └──────────┘  │       │  │         │  │          │  │  │
│   │                │       │  │         │  └──────────┘  │  │
│   │  ┌──────────┐  │       │  │         │                │  │
│   │  │          │  ├─────► │  │         │                │  │
│   │  │          │  │       │  │         │  ┌──────────┐  │  │
│   │  │          │  │       │  │         │  │          │  │  │
│   │  │     t3   │  │       │  │         │  │          │  │  │
│   │  │          │  │       │  │ ◄───────┤  │    t4    │  │  │
│   │  │          │  │       │  │         │  │          │  │  │
│   │  │          │  │       │  │         │  └──────────┘  │  │
│   │  └──────────┘  │       │  │         │                │  │
│   │                │       │  │         │  ┌──────────┐  │  │
│   │   ┌────────┐   │       │  │         │  │          │  │  │
│   │   │        │   ├────►  │  │         │  │          │  │  │
│   │   │   t5   │   │       │  │         │  │    t6    │  │  │
│   │   │        │   │       │  │  ◄──────┤  │          │  │  │
│   │   └────────┘   │       │  │         │  └──────────┘  │  │
│   │                │       │  │         │                │  │
│   └────────────────┘       └──┘         └────────────────┘  │
│                                                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘
LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 2)
Ответ на: комментарий от alysnix

борьба с дедлоками? такой проблемы не видно.

ее не существует в общем случае

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

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

Порядка нет.

да есть порядок. данные иерархичны и прицепленные к ним мьютексы - тоже.

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

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

В общем случае граф совсем не дерево, и эта проблема существует, и с этой проблемой борются.

пример давай. если проблема «существует» - значит должен быть очевидный пример. логично?

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

Тривиальный цикл из вики.

если проблема «существует» - значит должен быть очевидный пример.

Если проблемы «не существует», то почему его пытаются решать? Алогично?

Логика не полна, ей все проблемы не опишешь. А у некоторых логика противоречива, вот они любую теорию докажут.

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

базар про сталкера, бенчи каких-то счетчиков, тетю в чернигове и бузину в огороде кончай. по делу говори

Про сталкера — это тру стори, чел годами вилкой говно чистил в OpenXRay:

Макака ищет работу, C, Python, JS, либо челендж в опенсорсе на C++ (комментарий)

Если твой код не дедлочится, если это не hello world, и он не на глобальной блокировке, то с большой вероятностью у тебя в коде есть гонки. То есть, какие-то два зависимых куска кода выполняются без синхронизации — примерно так, как ты описал:

тут конкуренция на b и потом на a. сначала берешь b под мьютексом(спинлоком), отпускаешь b и пишешь в a под спинлоком

А по факту значения ячеек зависимы, и словишь ты это ошибку раз в год, когда гонка тригернется. Еще, например, в epoll линуксовом недавно такую ошибку выловили, там на бенчах раз в несколько миллионов запросов терялось событие ядра. «Ну подумаешь, потерялся запрос, да и хрен с ним, клиент пошлет его по второму кругу» — это то, что ты предлагаешь, но это не решение.

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

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

Проблема в том, что если таких ячеек много, то накроется одной общей блокировкой вся программа — как CPython, Ruby, и прочие прелести софтостроения. Да, в случае задачи обедающих философов введение «официанта» решает проблему. А теперь представь, что «философов» у тебя миллионов. То есть, параллельности там очень много, практически никогда конфликтов у тебя не будет — а ты предлагаешь одну блокировку на всё лепить, чтобы по ней все философы конфликтовали.

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

Ну что значит «доказал».

В математическом смысле доказал.

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

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

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

Я писал в статье, что предварительное взятие всех блокировок — это 100% гарантия от дедлоков, но вся проблема в том, что в реальных проектах не получается заранее знать, что и в каком порядке придется брать. Представь, что ты не знаешь заранее, какие тебе ячейки нужны будет, и узнаешь только при чтении ресурсов под блокировкой. Как ты будешь гарантировать порядок в таком случае? Это и есть тот самый циклический граф зависимостей, про который говорит анон.

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

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

Еще, например, в epoll линуксовом недавно такую ошибку выловили

не пиши никогда рядом такие предложения.

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

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

ты вообще понимаешь, что говоришь? ты говоришь, что у тебя b зависит от a, и a зависит от b. у тебя по сути а и б невычислимы в общем случае… и ты этот случай невычислимости натягиваешь на дедлоки.

ты как собрался вычислять ОДНВОМЕНЕННО две переменные, что друг от друга зависят? просто покажи алгоритм для общего случая.

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

Чел, ну жёваный стыд, у тебя к 2k19 не образовалось хоть каких-то аргументов, кроме «чтобы было хорошо, не надо делать плохо, а у кого плохо - тот не умеет»?

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

Ты уже решил тривиальный пример дедлока?

этот пример знаешь только ты. напиши его тут и пусть его все узнают.

alysnix ★★★
()

название статьи не располагает к прочтению.

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

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

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

ты говоришь, что у тебя b зависит от a, и a зависит от b. у тебя по сути а и б невычислимы в общем случае

Пф-ф-ф: взять из аккаунта a 100$ и положить их в b, взять из аккаунта b 100$ и положить их в аккаунт a. Да, они взаимозависмы, и прекрасно вычисляемы при этом. Что характерно, результат этих операций не зависит от их порядка. Да, это не «общий случай», но программы, где «всё зависит от всего» — это довольно частая ситуация.

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

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

я где предлагал «лепить» одну блокировку??? я предлагал не гнать пургу про дедлоки и не кошмарить народ ерундой.

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

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

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