Недавно я столкнулся с проблемами, пытаясь создать параллельную систему с использованием «Lock Guards», возвращаемого RwLock. Мне нужно было хранить эти блокировки из-за архитектурного дизайна моей системы. К моему удивлению, типы, в которых хранились эти охранники блокировки, не смогли реализовать черту Send, что побудило меня изучить реализацию этих охранников в исходном коде, и, конечно же, я обнаружил черту !Send, реализованную для этих типов.
Я не смог найти никакого реального объяснения того, почему для этих типов реализована черта !Send. Так почему же такое поведение определено в стандартной библиотеке Rust?
(Я предполагаю, что RwLock использует в своей структуре sys::RwLock, который хранит AtomicU32, который должен быть локальным состоянием потока, потому что в целом мы не можем передавать что-либо через границу потока, которая зависит от локального состояния потока нить там сгенерировал блокировку, но опять же я не совсем уверен)





Это связано с тем, что на некоторых платформах блокировку необходимо снять в том же потоке, в котором она была получена. Поскольку Rust использует примитивы синхронизации платформы, он должен этого придерживаться.
Например, ReleaseSRWLockExclusive(), который используется в Windows <= 7.
Если вам нужны отправляемые охранники, вы можете использовать park_lot с функцией send_guard.
@mitesh Потому что park_lot не использует замки платформы. Он реализует блокировки вручную.
Но не будет ли это неэффективно? Но на странице crates.io указано, что он в 1,5 раза быстрее. Есть ли какие-то алгоритмические изменения, которые сделают его более эффективным?
@mitesh Это может удивить, но примитивы синхронизации, предоставляемые ОС, часто работают медленнее, чем возможно, а иногда и намного медленнее. Современные операционные системы также предоставляют более быстрые примитивы (фьютексы), и сегодня их использование в Rust было возможно, поэтому я не знаю, работает ли park_lot по-прежнему в 1,5 раза быстрее (а иногда и медленнее - только сегодня я увидел это в тесте), но в этом нет необходимости. выполнение системного вызова по-прежнему является преимуществом, и я слышал, что park_lot все еще иногда работает быстрее.
Не могли бы вы предоставить некоторые ресурсы, где я могу понять, почему это так? Я понимаю, что сохранение системных вызовов — это огромное преимущество, но это также может означать, что мы ставим под угрозу надежность, поскольку примитив на основе ОС может фактически использовать семафоры и атомарные операции, предоставляемые в ядре, для обеспечения такого поведения блокировки, но эти операции могут быть перенесены в пользовательское пространство. .
Чем механизм блокировки в park_lot отличается от механизма блокировки в стандартной библиотеке, если ему также необходимо выделить блокировку с помощью базового вызова ОС?