Общий ответ:
Мьютексы - это концепция операционной системы. Операционная система, предлагающая мьютексы, должна гарантировать, что эти мьютексы работают правильно на всем оборудовании, которое эта операционная система хочет поддерживать. Если реализация мьютекса невозможна для конкретного оборудования, операционная система не может предложить мьютексы на этом оборудовании. Если для правильной работы операционной системы требуется наличие мьютексов, она вообще не может поддерживать это оборудование. То, как операционная система реализует мьютексы для определенного оборудования, неудивительно, что аппаратно зависит от него и сильно зависит от операционной системы и поддерживаемого оборудования.
Подробный ответ:
Наиболее общийЦП специального назначения предлагают атомарные операции. Эти операции разработаны так, чтобы быть атомарными для всех ядер ЦП в системе, независимо от того, являются ли эти ядра частью одного или нескольких отдельных ЦП.
Всего с двумя атомарными операциями atomic_or
и atomic_and
,можно реализовать блокировку. Например, подумайте о
int atomic_or ( int * addr, int val )
Атомно вычисляет *addr = *addr | val
и возвращает старое значение *addr
до выполнения вычисления. Если *lock == 0
и несколько потоков вызывают atomic_or(lock, 1)
, то только один из них получит 0
в качестве результата;только первый поток, чтобы выполнить эту операцию. Все остальные темы получают 1
в результате. Один поток, получивший 0
, является победителем, он имеет блокировку, все остальные потоки регистрируются на событие и переходят в спящий режим.
Поток победителя теперь имеет эксклюзивный доступ к разделу, следующему за atomic_or
, он может выполнить желаемую работу и, как только это будет сделано, он просто снова снимает блокировку (atomic_and(lock, 0)
) и генерирует системное событие, что блокировка теперь снова доступна.
Затем система активируетсяодин, несколько или все потоки, которые зарегистрировались для этого события перед сном, и гонка за блокировкой начинается заново. Либо один из пробужденных потоков выиграет гонку, либо, возможно, не один из них, так как другой поток был еще быстрее и, возможно, захватил блокировку между atomic_and
и еще до того, как другие потоки были пробуждены, но это нормально и до сих порправильно, так как это все еще только один поток, имеющий доступ. Все потоки, которым не удалось получить блокировку, возвращаются в спящий режим.
Конечно, фактические реализации современных систем зачастую намного сложнее, чем они, они могут принимать во внимание такие вещи, как приоритеты потоков (потоки с высоким prio могутбыть предпочтительным в гонке блокировок) или может гарантировать, что каждый поток, ожидающий мьютекс, в конечном итоге также получит его (существуют меры предосторожности, которые не позволяют потоку всегда проигрывать блокировку). Кроме того, мьютексы могут быть рекурсивными, и в этом случае система гарантирует, что один и тот же поток может получить один и тот же мьютекс несколько раз без взаимоблокировки, и это требует некоторого дополнительного учета. им требуется, чтобы ядра системы синхронизировали их работу, и это замедлит их обработку. Они могут быть несколько дорогими, если все ядра работают на одном процессоре, но они могут даже быть очень дорогими, если имеется несколько процессоров, поскольку синхронизация должна осуществляться по системе шин CPU, которая соединяет процессоры друг с другом, а эта система шин обычно неработать на уровне скорости процессора.
С другой стороны, использование мьютексов всегда будет тормозить обработку с самого начала, поскольку предоставление эксклюзивного доступа к ресурсам должно замедлять обработку, если нескольким потокам одновременно необходим доступ для продолжения их работы. Так что для реализации мьютексов это не имеет значения. На самом деле, если вы можете реализовать функцию потокобезопасным способом, используя только атомарные операции вместо полнофункциональных мьютексов, у вас довольно часто будет заметное преимущество в скорости, несмотря на то, что эти операции стоят дороже, чем обычные операции.