Безопасная конкурентность
Обеспечение безопасной и эффективной работы с конкурентным программированием — ещё одна из главных целей Rust. Конкурентное программирование, при котором разные части программы выполняются независимо, и параллельное программирование, при котором разные части программы выполняются одновременно, становятся всё более важными по мере того, как компьютеры всё чаще используют несколько процессоров. Исторически программирование в таких контекстах было сложным и подверженным ошибкам. Rust надеется изменить это.
Изначально команда Rust считала, что обеспечение безопасности памяти и предотвращение проблем с конкурентностью — это две отдельные задачи, требующие разных методов. Со временем команда обнаружила, что система владения и система типов представляют собой мощный набор инструментов для управления как безопасностью памяти, так и проблемами конкурентности! Благодаря использованию владения и проверки типов многие ошибки конкурентности в Rust являются ошибками времени компиляции, а не времени выполнения. Поэтому, вместо того чтобы тратить много времени на попытки воспроизвести точные обстоятельства возникновения ошибки конкурентности во время выполнения, некорректный код просто не скомпилируется и выдаст ошибку с объяснением проблемы. В результате вы можете исправить код в процессе работы над ним, а не потенциально после его отправки в продакшен. Мы назвали этот аспект Rust безопасной конкурентностью (fearless concurrency). Безопасная конкурентность позволяет писать код, свободный от тонких ошибок, и легко рефакторить его, не внося новых ошибок.
Примечание: Для простоты мы будем называть многие проблемы конкурентными, а не уточнять, конкурентные и/или параллельные. В этой главе, пожалуйста, мысленно заменяйте конкурентные и/или параллельные каждый раз, когда мы используем конкурентные. В следующей главе, где различие важнее, мы будем более конкретны.
Многие языки догматичны в отношении решений, которые они предлагают для решения проблем конкурентности. Например, Erlang имеет элегантную функциональность для конкурентности на основе передачи сообщений, но имеет лишь запутанные способы разделения состояния между потоками. Поддержка только подмножества возможных решений — это разумная стратегия для языков более высокого уровня, поскольку такой язык обещает выгоды от отказа от части контроля ради получения абстракций. Однако от языков более низкого уровня ожидают, что они предоставят решение с наилучшей производительностью в любой данной ситуации и имеют меньше абстракций над аппаратным обеспечением. Поэтому Rust предлагает разнообразные инструменты для моделирования проблем любым подходящим для вашей ситуации и требований способом.
Вот темы, которые мы рассмотрим в этой главе:
- Как создавать потоки для одновременного выполнения нескольких фрагментов кода
- Конкурентность на основе передачи сообщений, при которой каналы отправляют сообщения между потоками
- Конкурентность на основе разделяемого состояния, при которой несколько потоков имеют доступ к некоторому фрагменту данных
- Типажи
SyncиSend, которые распространяют гарантии конкурентности Rust на пользовательские типы, а также на типы, предоставляемые стандартной библиотекой