Использует ли заголовок C ++ <mutex>аппаратную поддержку при обеспечении параллелизма или является чисто решением на основе алгоритма - PullRequest
0 голосов
/ 11 марта 2020

Как мьютекс C ++ реализован под капотом? Использует ли он только алгоритмы Декера, Петерсона или другие для обеспечения взаимного исключения или же использует аппаратную поддержку, такую ​​как сравнение и обмен объявлениями с прерываниями (CAS).

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

Ответы [ 3 ]

2 голосов
/ 11 марта 2020

В Linux, когда мьютекс не выполняется, блокировка и разблокировка происходят в пространстве пользователя только с использованием инструкций atomi c, таких как сравнение и замена. В утверждало случае вызова в ядро ​​требуется ждать на мьютекс, пока он был разблокирован (на замке) или просыпаться официантов (на разблокировку). Блокировка мьютексов пространства пользователя не отключает прерывания.

Вот исходный код низкоуровневых мьютексных примитивов в glibc, комментарии поучительны:

/* Low-level locks use a combination of atomic operations (to acquire and
   release lock ownership) and futex operations (to block until the state
   of a lock changes).  A lock can be in one of three states:
   0:  not acquired,
   1:  acquired with no waiters; no other threads are blocked or about to block
       for changes to the lock state,
   >1: acquired, possibly with waiters; there may be other threads blocked or
       about to block for changes to the lock state.

   We expect that the common case is an uncontended lock, so we just need
   to transition the lock between states 0 and 1; releasing the lock does
   not need to wake any other blocked threads.  If the lock is contended
   and a thread decides to block using a futex operation, then this thread
   needs to first change the state to >1; if this state is observed during
   lock release, the releasing thread will wake one of the potentially
   blocked threads.

   Much of this code takes a 'private' parameter.  This may be:
   LLL_PRIVATE: lock only shared within a process
   LLL_SHARED:  lock may be shared across processes.

   Condition variables contain an optimization for broadcasts that requeues
   waiting threads on a lock's futex.  Therefore, there is a special
   variant of the locks (whose name contains "cond") that makes sure to
   always set the lock state to >1 and not just 1.

   Robust locks set the lock to the id of the owner.  This allows detection
   of the case where the owner exits without releasing the lock.  Flags are
   OR'd with the owner id to record additional information about lock state.
   Therefore the states of robust locks are:
    0: not acquired
   id: acquired (by user identified by id & FUTEX_TID_MASK)

   The following flags may be set in the robust lock value:
   FUTEX_WAITERS     - possibly has waiters
   FUTEX_OWNER_DIED  - owning user has exited without releasing the futex.  */

И pthread_mutex_lock код .

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

2 голосов
/ 11 марта 2020

Стандарт требует наличия атома c операций. Не обязательно CAS, но, по крайней мере, обмен. std::atomic_flag требуется, чтобы быть истинными атомами c, хотя CAS является излишним для него, простой обмен является удовлетворительным.

Обратите внимание, что любой алгоритм, такой как Деккер, Петерсон или другой, по крайней мере, потребовал бы хранилище atomi c load и atomi c, и они не будут работать, если load и store не атоми c. Кроме того, типы не * Atomi c не предписывают упорядочение памяти, что подразумевается этими алгоритмами.

В действительности не требуется, чтобы std::mutex был основан на вызовах операционной системы и чтобы существовала операционная система. звонки на всех.

Теоретически, std::mutex может вращать только мьютекс.

Он также может блокировать только мьютекс.

На практике хорошая реализация сначала пыталась бы обработать блокировку с помощью atomi c, но когда она прибегает к ожиданию, она будет ждать ОС.

2 голосов
/ 11 марта 2020

Он просит операционную систему сделать это.

На Linux, который, вероятно, будет использовать pthreads ( Как pthread реализован в linux ядре 3.2? ).

На Windows это с Windows API. Вы можете попытаться задать вопрос об этом в Microsoft.

В стандартной реализации библиотеки не будет прямого доступа к оборудованию. Это то, для чего предназначены операционные системы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...