Concorrência Extensível com Send e Sync

Beginner

This tutorial is from open-source community. Access the source code

Introdução

Bem-vindo(a) a Concorrência Extensível com as Traits Send e Sync. Este laboratório faz parte do Livro do Rust. Você pode praticar suas habilidades em Rust no LabEx.

Neste laboratório, exploramos os dois conceitos de concorrência em Rust - as traits Send e Sync, que fornecem capacidades de concorrência extensíveis além da biblioteca padrão.

Concorrência Extensível com as Traits Send e Sync

Curiosamente, a linguagem Rust possui muito poucas funcionalidades de concorrência. Quase todas as funcionalidades de concorrência sobre as quais falamos até agora neste capítulo fazem parte da biblioteca padrão, e não da linguagem. Suas opções para lidar com concorrência não se limitam à linguagem ou à biblioteca padrão; você pode escrever suas próprias funcionalidades de concorrência ou usar aquelas escritas por outros.

No entanto, dois conceitos de concorrência estão embutidos na linguagem: as traits std::marker Send e Sync.

Permitindo a Transferência de Propriedade entre Threads com Send

O trait marcador Send indica que a propriedade de valores do tipo que implementa Send pode ser transferida entre threads. Quase todos os tipos Rust são Send, mas existem algumas exceções, incluindo Rc<T>: este não pode ser Send porque se você clonasse um valor Rc<T> e tentasse transferir a propriedade do clone para outra thread, ambas as threads poderiam atualizar a contagem de referência ao mesmo tempo. Por esta razão, Rc<T> é implementado para uso em situações de thread único onde você não quer pagar a penalidade de desempenho thread-safe.

Portanto, o sistema de tipos e as restrições de traits do Rust garantem que você nunca pode, acidentalmente, enviar um valor Rc<T> entre threads de forma insegura. Quando tentamos fazer isso na Listagem 16-14, recebemos o erro the trait Send is not implemented for Rc<Mutex<i32>>. Quando mudamos para Arc<T>, que é Send, o código compilou.

Qualquer tipo composto inteiramente por tipos Send é automaticamente marcado como Send também. Quase todos os tipos primitivos são Send, exceto os ponteiros brutos (raw pointers), que discutiremos no Capítulo 19.

Permitindo Acesso de Múltiplas Threads com Sync

A trait marker Sync indica que é seguro para o tipo que implementa Sync ser referenciado de múltiplas threads. Em outras palavras, qualquer tipo T é Sync se &T (uma referência imutável para T) é Send, o que significa que a referência pode ser enviada com segurança para outra thread. Semelhante a Send, os tipos primitivos são Sync, e os tipos compostos inteiramente por tipos que são Sync também são Sync.

O smart pointer Rc<T> também não é Sync pelas mesmas razões que não é Send. O tipo RefCell<T> (sobre o qual falamos no Capítulo 15) e a família de tipos relacionados Cell<T> não são Sync. A implementação da verificação de empréstimo (borrow checking) que RefCell<T> faz em tempo de execução não é thread-safe. O smart pointer Mutex<T> é Sync e pode ser usado para compartilhar acesso com múltiplas threads, como você viu em "Compartilhando um Mutex<T> Entre Múltiplas Threads".

Implementar Send e Sync Manualmente é Inseguro

Como os tipos que são compostos pelas traits Send e Sync são automaticamente também Send e Sync, não precisamos implementar essas traits manualmente. Como traits marcadores, elas nem sequer têm nenhum método para implementar. Elas são apenas úteis para impor invariantes relacionadas à concorrência.

Implementar manualmente essas traits envolve implementar código Rust inseguro (unsafe). Falaremos sobre o uso de código Rust inseguro no Capítulo 19; por enquanto, a informação importante é que a construção de novos tipos concorrentes que não são compostos por partes Send e Sync requer uma reflexão cuidadosa para manter as garantias de segurança. "The Rustonomicon" em https://doc.rust-lang.org/stable/nomicon tem mais informações sobre essas garantias e como mantê-las.

Resumo

Parabéns! Você concluiu o laboratório Extensible Concurrency With the Send and Sync Traits. Você pode praticar mais laboratórios no LabEx para aprimorar suas habilidades.