Реентерабельность и потокобезопасностьВезде в документации термины реентерабельность и потокобезопасность используются для обозначения классов и функций для указания того, как они могут быть использованы в многопоточных приложениях:
Таким образом, потокобезопасная функция всегда реентерабельна, но реентерабельная функция не всегда потокобезопасна. В более широком смысле, класс называется реентерабельным, если его функции-члены могут быть безопасно вызваны из нескольких потоков, пока каждый поток использует свой отдельный экземпляр класса. Класс является потокобезопасным, если его функции-члены могут быть безопасно вызваны из нескольких потоков, даже если все потоки используют один и тот же экземпляр класса. Замечание: Классы Qt документируются как потокобезопасные, только если они предназначены для работы в многопоточных приложениях. Если функция не помечена как потокобезопасная или реентерабельная, то она не должна использоваться в разных потоках. Если класс не помечен как потокобезопасный или реентерабельный, то к конкретному экземпляру класса не должно быть доступа из разных потоков. РеентерабельностьКлассы C++ часто реентерабельны просто потому, что они имеют доступ только к данным своих членов. Любой поток может вызвать функцию-член экземпляра реентерабельного класса, в то время как ни один другой поток не может вызвать функцию-член того же самого экземпляра класса в тоже самое время. Например, нижеуказанный класс Counter является реентерабельным: class Counter { public: Counter() { n = 0; } void increment() { ++n; } void decrement() { --n; } int value() const { return n; } private: int n; }; Данный класс не является потокобезопасным, поскольку если несколько потоков попытаются изменить член данных n, результат будет не определен. Это так, потому что операторы ++ и -- не всегда атомарны. В действительности, они обычно расширяются до трех машинных инструкций:
Потоки A и B одновременно могут загрузить старое значение переменной, увеличить ее значение в регистре и сохранить значение переменной в памяти, но переменная будет увеличена только однажды! ПотокобезопасностьПоток A должен выполнить шаги 1, 2, 3 без прерывания (атомарно) прежде, чем поток B сможет выполнить те же шаги; или наоборот. Самый легкий способ создания потокобезопасного класса состоит в том, чтобы защитить весь доступ к членам данных с помощью QMutex: class Counter { public: Counter() { n = 0; } void increment() { QMutexLocker locker(&mutex); ++n; } void decrement() { QMutexLocker locker(&mutex); --n; } int value() const { QMutexLocker locker(&mutex); return n; } private: mutable QMutex mutex; int n; }; Класс QMutexLocker автоматически запирает мьютекс в своем конструкторе и отпирает его в деструкторе, вызываемом при завершении функции. Запирание мьютекса гарантирует, что обращения из разных потоков будут упорядочены. Член данных mutex объявлен как mutable, потому что позволяет запереть и отпереть мьютекс в функции value(), которая является константной. Замечания по классам QtБольшинство классов Qt реентерабельны, но не потокобезопасны, поскольку такая реализация потребовала бы дополнительных издержек на многократные блокировки и разблокировки QMutex. Например, QString реентерабелен, но не потокобезопасен. Вы можете смело обращаться к различным экземплярам класса QString из нескольких потоков одновременно, но вы не можете спокойно получить доступ к одному и тому же экземпляру QString из нескольких потоков одновременно (если вы самостоятельно не обеспечиваете защиту от доступа с помощью QMutex). Некоторые классы и функции Qt потокобезопасны. Это, главным образом, связанные с потоками классы (например, QMutex) и фундаментальные функции (например, QCoreApplication::postEvent()). Замечание: Терминология в многопоточной области еще не полностью стандартизована. POSIX использует несколько отличающиеся определения реентерабельности и потокобезопасности для своих API C. При использовании других объектно-ориентированных библиотек классов C++ совместно с Qt убедитесь, что их определения понятны. |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |