Используйте стандартный С++
В своем коде вы используете EnterCriticalSection()
и LeaveCriticalSection()
< /a> функции Microsoft WinAPI.
У них есть несколько серьезных неудобств: во-первых, они не переносимы, во-вторых, они небезопасны: что произойдет, если исключение заставит поток покинуть ReadData()
неожиданным образом? Вы можете в конечном итоге получить критический раздел, который кажется окнам не оставленным, что приведет к голоданию всех других потоков!
Стандартная альтернатива C++ с использованием lock_guard
на mutex
, как продемонстрировал Вернер, намного безопаснее: во-первых, она переносима на разные платформы. , но, кроме того, он реализует идиому RAII, которая гарантирует, что в случае неожиданного исключения lock_guard
уничтожается при выходе из функции, в результате чего mutex
освобождается.
Использование atomic может быть недостаточным
Очень часто люди испытывают искушение использовать атомарные методы, потому что они избегают гонок данных и создают впечатление, что они решат все проблемы синхронизации потоков.
К сожалению, это не так. Как только вы используете несколько атомарных элементов, вы можете сделать предположение об общей согласованности, тогда как на самом деле все может происходить по-другому и вызывать очень неприятные ошибки. Создание безблокировочных алгоритмов и структур данных чрезвычайно сложно и сложно. Поэтому я настоятельно рекомендую прочитать прекрасную книгу Энтони Уильяма C++ concurrency in action: он подробно исследует все связанные аспекты.
Другие альтернативы
В своем вопросе вы ссылаетесь на вектор. Поддерживать вектор, безопасный для параллельных потоков, очень сложно, потому что, по сути, всякий раз, когда емкость вектора должна быть расширена, может произойти перераспределение, делающее недействительными все итераторы и указатели на этот вектор, где бы они ни использовались. К счастью, существуют некоторые потокобезопасные реализации, такие как библиотека параллельных шаблонов от Microsoft.
С другой стороны, если вы используете вектор только для хранения строк файла и их последовательной обработки, вы также можете рассмотреть возможность использования очереди с тем преимуществом, что вы можете использовать одну из многих доступных реализаций потокобезопасности, например например, boost.
person
Christophe
schedule
27.10.2017
std::mutex
основан на блокировках SRW. В предыдущих версияхstd::mutex
сильно ломался и мог вызывать взаимоблокировки. Например, если вы вызоветеstd::mutex::lock()
в первый раз изDllMain
, он заблокируется. - person StaceyGirl   schedule 27.10.2017std::mutex
для C++11 (поскольку вам нужно, чтобы его конструктор былconstexpr
, который все еще не работает, по крайней мере, на VS2015). Насчет тупика: да, всегда и безоговорочно. И я знаю, что причина взаимоблокировки заключается в том, что никто не ожидает, что блокировка мьютекса заблокирует другой дополнительный мьютекс внутри. Так что да,std::mutex
не работает в VS до 2015 года. Как и условные переменные. - person StaceyGirl   schedule 27.10.2017std::mutex
в VS2013 и более ранних версиях основана на некоторой среде выполнения Concurrency, которая инициализируется лениво. По сути, он попытается выполнить какую-то хитрую инициализацию и зависнет где-то в RegisterWaitForSingleObject. Имейте в виду, что все это можно сделать с помощью одного потока в процессе и мьютекса, созданного в стеке - в пользовательском коде нет взаимоблокировки. - person StaceyGirl   schedule 27.10.2017NtWaitForAlertByThreadId
, которые не создают дополнительных объектов - person RbMm   schedule 27.10.2017std::mutex
не сломан. Как указано в рекомендациях по работе с DLL внутри DllMain никогда не следует синхронизировать с другими потоками. Это может привести к взаимоблокировке.. Это связано с тем, что самые простые API-интерфейсы, такие как GetModuleFileName, получают блокировку загрузчика, которую уже удерживает DllMain. - person rustyx   schedule 27.10.2017RegisterWaitForSingleObject
до завершения инициализации процесса (до точки входа exe), потому что этот API ожидает запуска рабочего потока, но рабочий поток ожидает завершения инициализации процесса. Эта ошибка исправлена в win8.1. но в любом случае не безусловный (если dll загрузить позже, при инициализации процесса - тупика нет). но src - ошибка попробуйте подождать внутри блокировки загрузчика - person RbMm   schedule 27.10.2017