|
0 / 0 / 0
Регистрация: 04.06.2022
Сообщений: 24
|
||||||
Вопрос по многопоточности18.07.2025, 22:33. Показов 13367. Ответов 104
Метки concurrency (Все метки)
Здравствуйте, сейчас смотрю книги по многопоточности, возникло несколько вопросов. Почему-то слово "вопрос" нельзя полностью написать в заголовке.
1. Известно, что переменную bool (или int, неважно) может 1 раз записать только 1 поток, остальные только читают, зачем тогда делать её atomic? 2. Улетят ли вызовы notify_one/notify_all вникуда, если они много раз вызваны перед методами, которые ожидают cv? 3. Допустим, есть 5 потоков и есть общий вектор с огромным количеством элементов. Первый поток изменяет только элементы с идексами 0, 5, 10; второй поток - элементы с индексами 1, 6, 11; третий поток - элементы с индексами 2, 7, 12 и т.д. Правильно ли я понимаю, что переброска кэша и связанное с ним замедление программы все равно может происходить, потому что индексы, с которыми работает каждый поток, находятся по соседству? 4. Вот пример потокобезопасной очереди из книги Вилльямса. Зачем при сравнении head с tail в функции get_tail мы используем мьютекс, который тут же перестает блокироваться после того, как мы вышли из функции?
0
|
||||||
| 18.07.2025, 22:33 | |
|
Ответы с готовыми решениями:
104
Управление потоками в многопоточности Нужна информация о многопоточности |
|
фрилансер
6450 / 5651 / 1129
Регистрация: 11.10.2019
Сообщений: 15,049
|
||
| 19.07.2025, 08:42 | ||
|
Но если была гарантия, что переменная уже инициализирована и больше меняться не будет, а только потом были запущены читающие потоки, то всё ок
1
|
||
|
0 / 0 / 0
Регистрация: 04.06.2022
Сообщений: 24
|
|||||||||
| 20.07.2025, 15:57 [ТС] | |||||||||
Добавлено через 9 минут Например, в этом коде может печататься на 123, а цифры в другом порядке, но если перед каждым bool поставить volatile или использовать atomic<bool>, то будет печататься 123, как и ожидали. Понятно, почему работает с atomic или volatile , но почему без них не работает?
0
|
|||||||||
|
фрилансер
6450 / 5651 / 1129
Регистрация: 11.10.2019
Сообщений: 15,049
|
|||
| 20.07.2025, 18:45 | |||
std::atomic - решаетА вывод в std::cout здесь может замаскировать проблему, так как к нему доступ синхронизирован внутри класса
1
|
|||
| 20.07.2025, 21:03 | |||
1
|
|||
|
0 / 0 / 0
Регистрация: 04.06.2022
Сообщений: 24
|
||
| 20.07.2025, 22:18 [ТС] | ||
|
"TBB provides threadsafe containers and some parallel algorithms, whereas OpenMP is more of a way to parallelise existing code." "TBB предоставляет потокобезопасные контейнеры и некоторые параллельные алгоритмы, тогда как OpenMP — это скорее способ распараллелить существующий код." Похоже, что с TBB надо ознакомиться, а OpenMP изучить более внимательно, так? Посоветуйте, пожалуйста, литературу, а также то, с чего начать с TBB или с OpenMP .
0
|
||
| 20.07.2025, 23:51 | ||||||||
0
|
||||||||
|
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
|
|||||
| 21.07.2025, 13:50 | |||||
tail не под блокировкой в функции get_tail(), то конечно же будет.Это конкурентная операция чтения и она, как минимум, должна быть атомарной. Но, что еще более важно, тут необходимо обеспечить межпоточную синхронизацию: в функции push() три операции записи (на самом деле их там сколь угодно много), и поток, выполняющий pop(), должен увидеть их именно в том порядке, в котором их делает поток, выполняющий push() (что будет при нарушении консистентности данных, можете пофантазировать самостоятельно). Мьютекс обеспечивает синхронизацию acquire/release.
2
|
|||||
|
0 / 0 / 0
Регистрация: 04.06.2022
Сообщений: 24
|
||||
| 21.07.2025, 19:07 [ТС] | ||||
|
Если очередь пустая, то мы получаем старое значение tail (tail==head), возвращаем пустое значение, а далее нам не важно, что делает push, главное, что с помощью мьютекса внутри get_tail сравнение происходит уже с копией старого значение и не произошло UB по причине одновременного чтения и записи по одному адресу. А то, что значение tail в пустой очереди могло поменяться, это уже никак не волнует, правильно?
0
|
||||
|
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
|
||
| 21.07.2025, 20:13 | ||
|
Например, представьте, что очередь пуста, и два потока "одновременно" осуществляют доступ - один pop(), второй push(). Тот, который делает push(), увидел изменение tail (очередь не пуста), но не увидел, например, изменения в head->next (он по-прежнему nullptr), что в этом случае произойдет?
0
|
||
| 21.07.2025, 21:41 | ||||||||||
0
|
||||||||||
|
0 / 0 / 0
Регистрация: 04.06.2022
Сообщений: 24
|
|||||||||||||||||
| 21.07.2025, 22:36 [ТС] | |||||||||||||||||
0
|
|||||||||||||||||
|
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
|
|||||||||
| 21.07.2025, 23:56 | |||||||||
|
Не по теме:
[basic.exec] Так вот, под "порядком" я имел ввиду, что нужны гаранти того, что, например, запись tail->data в push happens before чтения head->data в pop.И это база языка, которую неплохо бы освоить. В конце концов кому-то же придется в этом разбираться и поддерживать, когда все существующие обитатели "дурки" отойдут дел. cdcodecpp, вы пока летите вперед паровоза. Пока просто примите то, что чтение tail не должно быть конкурентным с его записью, поэтому нужен mutex. Кликните здесь для просмотра всего текста
Чуть позже, в 5 главе, по-моему, вы познакомитесь с атомарными операциями и узнаете, что порядок модификации памяти объектов одним потоком может отличаться от наблюдаемого другим, т.е.:
0
|
|||||||||
|
0 / 0 / 0
Регистрация: 04.06.2022
Сообщений: 24
|
|||||||||||||
| 22.07.2025, 00:09 [ТС] | |||||||||||||
Кроме предотвращения данного UB мьютекс решает ещё какие-либо проблемы? Появятся ли проблемы без мьютекса именно у тех 2 строк, которые написаны ниже?
0
|
|||||||||||||
| 22.07.2025, 01:15 | |||||||
Что мне будет если пишу/читаю одновременно? Получу старое значение tail (но не мусор) и не сделаю pop (который был возможен)? Так мне все равно с этим надо считаться, push мог просто случиться позже. Вот если бы стал лезть внутрь старого tail - тогда да. Детский пример
![]() Не по теме: За ссылки на стандарт спасибо, но его нужно читать только когда совершенно точно известно что найти. По-другому у меня никогда не выходило :)
0
|
|||||||
|
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
|
||||||
| 22.07.2025, 15:38 | ||||||
|
К UB приводят не какие-то события во время выполнения, а ошибки в написании кода. UB буквально переводится как неопределенное поведение. Т.е. нет смысла вообще рассуждать, как и что будет происходить в работающей программе, её поведение не определено с точки зрения языка. На самом деле она конечно же ведет себя вполне определенно, и вы можете это поведение исследовать анализируя машинный код, но это все не имеет смысла и я попытаюсь объяснить почему. Нет такого понятия "одновременно" в языке. Вы пытаетесь представить выполнение кода так, как он написан на высокоуровневом языке, да еще и построчно. Но нужно понимать, что это всего лишь умозрительный эксперимент, который не будет иметь отношения к реальности. Такой подход может как помогать в усвоении материала, так и вредить. В вашем случае скорее второе. Вы должны понимать, одна строчка кода на с++ будет превращена компилятором в несколько(иногда сотни и тысячи) машинных инструкций, среди которых будут инструкции записи и чтения памяти. В погоне за производительностью компилятору позволено переупорядочивать эти инструкции так, как он считает нужным, если это не нарушает требования стандарта. Кликните здесь для просмотра всего текста
Например, если на определенной платформе операции записи в соседние ячейки памяти быстрее, а ваш код развернулся в последовательность записей по адресам A и B в одной строке, и A + 1 в следующей, то очевидной оптимизацией будет переупорядочить их в последовательность A, A + 1, B.
Кликните здесь для просмотра всего текста
Да, знание "нижнего" уровня компьютерных технологий прояснит суть и причины высокоуровневых правил, но не является необходимым. Если вы не собираетесь работать на этом уровне, конечно же. Просто там огромный объем информации.
Итак, резюмируя вышесказанное, отвечу на ваш вопрос: get_tail() весь код некорректен, он не соответствует стандарту и содержит UB. Говорить о проблемах в каких либо строках не имеет смысла.2) Если вас интересует, почему чтение tail мы делаем под мьютексом, а чтение остального без (и нет ли тут проблемы), то ответ: захват мьютекса в get_tail() как бы решает две задачи - предоставляет исключительный доступ к tail напрямую(как бы делая его атомарным) и опосредованно упорядочивая (предоставляет единый глобальный порядок модификации памяти) доступ к остальному. Но подробно об этом вы узнаете чуть позже, пока не заморачивайтесь по этому поводу, всему свое время.Не по теме:
Что за детский сад? Что вы от меня хотите? Вы вроде ясно дали понять, что это трудно, вы в этом не разбираетесь и, самое главное, не хотите разбираться из-за опасений попасть в дурку. Зачем я буду тратить свое время на жевание кактуса? Если подойдете к вопросу серьезно, но возникнут трудности в понимании конкретных пунктов стандарта, я постараюсь помочь. Заниматься демагогией с вами я не собираюсь.
0
|
||||||
|
0 / 0 / 0
Регистрация: 04.06.2022
Сообщений: 24
|
|||||||
| 22.07.2025, 23:07 [ТС] | |||||||
А если бы команды не переупорядочивались компилятором и процессором, то всё равно было бы UB?
0
|
|||||||
| 23.07.2025, 00:46 | |||
|
1. Такое UB недопустимо, ошибка, нужно исправлять! Даже если сейчас нет проблем, они могут возникнуть в будущем! Такие ответы легко даются, когда "меня это не коснется", когда не нужно править старый код, часто писаный другими в незапамятные времена 2. Ничем особенным это UB не грозит, да, читающий "увидит" старое значение, это необязательно катастрофа. И вообще: "работает - не лезь" (хотя это конечно ничего не доказывает, баги всплывали и через годы). Да, это мое мнение 3. Хз, что такое "UB" - никто не знает. На всякий случай сделайте theMax atomic'ом, хуже не будет Вполне нормальный ответ практика 4. Это может быть корректно исправлено, для этого надо <..>. Идеальный ответ которого не случится. Ну, для полноты картины/списка
0
|
|||
| 23.07.2025, 01:46 | ||
|
Или вот др пример из той же книги (аттач). Далее там довольно пространные объяснения вникнуть в которые непросто. Поэтому "верно ли я понимаю что"
1
|
||
| 23.07.2025, 01:46 | |
|
Помогаю со студенческими работами здесь
20
изучение многопоточности Объясните принцип создания многопоточности Менеджмент жесткого диска при многопоточности Реализация многопоточности в консоли Сравнение многопоточности С++11 и WinAPI Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а привычная функция main(). . .
|
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net
REST сервисы временно не работают, только через Web.
Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
|
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
|
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
|
|
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма).
На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
|
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ *
Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи
и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
|
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым.
Но восстановить их можно так.
Для этого понадобится консольная утилита. . .
|
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
|