EnglishРусский Map

Rust Send и Sync

title
Rust Send и Sync
type
concept
summary
Два auto-trait'а потокобезопасности в Rust: Send для перемещения между потоками, Sync для разделяемых ссылок, с правилом &T: Send ⇔ T: Sync
tags
rust, type-system, concurrency
created
2026-05-10
updated
2026-07-29
lang
ru
translation_of
rust-send-sync
source_updated
2026-07-29
translated
2026-09-01
translator
lllm/antigravity/gemini-3.7-flash-medium

Send и Sync - два auto-trait'а потокобезопасности в Rust. Они выводятся автоматически (структура получает их тогда и только тогда, когда ими обладают все её поля) и определяют, что borrow checker разрешает делать между потоками:

  • T: Send - значения типа T можно перемещать в другой поток. Rc<T> не является Send (гонка при изменении счётчика ссылок); Arc<T> является Send, если T: Send + Sync.
  • T: Sync - &T можно разделять между потоками. Эквивалентно: T: Sync&T: Send. Cell<T> не является Sync (внутренняя мутабельность без синхронизации); для Mutex<T>: Sync требуется лишь T: Send.

Неочевидные правила, которые делают это критически важным на практике:

Тип Для Send требуется Для Sync требуется
&T T: Sync T: Sync
&mut T T: Send T: Sync
Box<T> T: Send T: Sync
Rc<T> никогда никогда
Arc<T> T: Send + Sync T: Send + Sync
Mutex<T> T: Send T: Send
RwLock<T> T: Send T: Send + Sync
Cell<T> T: Send никогда

Правило &T: Send ⇔ T: Sync часто оказывается неожиданным и служит причиной подводного камня в rust-async-trait-sync-bound - захват &self в Send-future неявно требует Self: Sync, даже когда в коде ничто явно об этом не просит.

Обходные пути, когда поле имеет тип !Sync, но требуется Send-future:

  • Обернуть поле в Mutex<T> - для Mutex<T>: Sync требуется только T: Send
  • Использовать &mut self вместо &self - для &mut T: Send нужен только T: Send
  • Сделать захваченное значение владеемым (переместить его в future) - выбор владения вместо заимствования снимает проблему

Для понимания логики дизайна языка (&mut как уникальность, а не мутабельность) канонической является статья Нико Мацакиса "Focusing on ownership". В safety-in-an-unsafe-world Send приводится как практический пример свойства безопасности, определённого библиотекой: смысл trait'а полностью заключён в комментарии к документации, unsafe impl служит реализацией гарантии, а ограничение F: Send у spawn обосновывает лежащий под ним вызов pthread_create.

См. также: rust-async-trait-sync-bound, message-passing-vs-shared-memory.

Sub-pages