Compartilhando com Arc e Mutex
Altere o estado compartilhado com segurança.
Compartilhando com Arc e Mutex é uma aula grátis de Learn Rust Coding no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Learn Rust Coding, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Learn Rust Coding inclui 4 aulas no total.
A necessidade de estado compartilhado
Às vezes, várias threads precisam ler ou atualizar os mesmos dados. Mover a propriedade para uma única thread não é suficiente.
O Rust oferece propriedade compartilhada segura entre threads com Arc e mutação segura com Mutex. Juntos, eles permitem um estado compartilhado e mutável.
Arc: contagem atômica de referências
Arc significa contagem atômica de referências. Ele é parecido com Rc, mas seu contador usa operações atômicas, por isso é seguro entre threads.
Fazer clone de um Arc não copia os dados. Apenas incrementa o contador e retorna outro handle para o mesmo valor.
use std::sync::Arc;
fn main() {
let shared = Arc::new(vec![1, 2, 3]);
let clone = Arc::clone(&shared);
println!("{:?} {:?}", shared, clone);
}Compartilhando Arc entre threads
Para compartilhar dados somente para leitura, faça um clone do Arc para cada thread e mova cada clone para dentro dela. Todas as threads apontam para a mesma alocação.
Como Arc é Send e Sync, isso compila sem problemas.
use std::sync::Arc;
use std::thread;
fn main() {
let data = Arc::new(vec![10, 20, 30]);
let mut handles = vec![];
for i in 0..3 {
let d = Arc::clone(&data);
handles.push(thread::spawn(move || println!("{}", d[i])));
}
for h in handles { h.join().unwrap(); }
}Arc sozinho permite apenas leitura
Arc fornece propriedade compartilhada, mas apenas acesso compartilhado e imutável ao valor interno.
Você não pode alterar dados diretamente por meio de um Arc, porque várias threads que o mantivessem ao mesmo tempo poderiam entrar em uma condição de corrida. Você precisa de mutabilidade interna com um lock.
Mutex: exclusão mútua
Um Mutex protege os dados para que apenas uma thread possa acessá-los por vez. Você chama lock para obter acesso.
lock retorna um Result; chamar unwrap fornece uma proteção de ponteiro inteligente. As outras threads ficam bloqueadas até que a proteção seja descartada.
use std::sync::Mutex;
fn main() {
let m = Mutex::new(0);
{
let mut guard = m.lock().unwrap();
*guard += 5;
}
println!("{:?}", m);
}A proteção e RAII
O valor retornado por lock é um MutexGuard. Você acessa os dados internos fazendo a desreferenciação com *.
Quando a proteção sai do scope, o lock é liberado automaticamente. Esse estilo RAII evita que você se esqueça de desbloquear.
Combinando Arc e Mutex
Para compartilhar estado mutável entre threads, envolva um Mutex em um Arc. O Arc compartilha a propriedade; o Mutex protege a mutação.
Esse padrão, Arc<Mutex<T>>, é a forma padrão de implementar estado compartilhado e mutável no Rust.
use std::sync::{Arc, Mutex};
fn main() {
let counter = Arc::new(Mutex::new(0));
let c = Arc::clone(&counter);
*c.lock().unwrap() += 1;
println!("{}", *counter.lock().unwrap());
}Um contador compartilhado
Aqui, dez threads incrementam cada uma um contador compartilhado. Cada uma faz clone do Arc, bloqueia o Mutex e adiciona um.
Como o lock serializa o acesso, o total final é sempre exatamente dez.
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let c = Arc::clone(&counter);
handles.push(thread::spawn(move || {
*c.lock().unwrap() += 1;
}));
}
for h in handles { h.join().unwrap(); }
println!("{}", *counter.lock().unwrap());
}Mantenha as seções críticas curtas
O código executado enquanto um lock está mantido é a seção crítica. As outras threads esperam nesse ponto, então mantenha-a curta.
Adquira o lock, faça a atualização mínima e depois libere-o. Evite cálculos pesados ou operações de entrada e saída enquanto mantiver o lock.
use std::sync::Mutex;
fn main() {
let m = Mutex::new(Vec::new());
{
let mut v = m.lock().unwrap();
v.push(1);
} // lock released here
println!("{:?}", m.lock().unwrap());
}Deadlocks e envenenamento
Se uma thread bloquear o mesmo Mutex duas vezes, ou se duas threads bloquearem dois mutexes em ordens opostas, poderá ocorrer um deadlock e o programa ficará travado para sempre.
Se uma thread entrar em panic enquanto mantém um lock, o Mutex será envenenado e chamadas posteriores a lock retornarão um Err.
RwLock para muitos leitores
Quando as leituras superam muito as gravações, RwLock pode ser melhor que Mutex. Ele permite vários leitores concorrentes ou um único escritor exclusivo.
Use read para acesso compartilhado e write para acesso exclusivo.
use std::sync::RwLock;
fn main() {
let lock = RwLock::new(5);
{
let r = lock.read().unwrap();
println!("read {}", *r);
}
*lock.write().unwrap() += 1;
println!("{}", *lock.read().unwrap());
}Verificação rápida
Teste sua compreensão sobre Arc e Mutex.
Recapitulação
Você aprendeu que Arc compartilha a propriedade entre threads usando contagem atômica de referências, mas permite apenas acesso imutável.
Um Mutex protege a mutação, fornecendo uma proteção que é liberada ao ser descartada. Combine-os como Arc<Mutex<T>> para obter estado compartilhado e mutável, prestando atenção a deadlocks e envenenamento.
A seguir, você fará join das threads e collect seus resultados.
Perguntas Frequentes
A aula “Compartilhando com Arc e Mutex” é grátis?
Sim — o texto completo de “Compartilhando com Arc e Mutex” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Learn Rust Coding, atualize para CoddyKit PRO. O curso de Learn Rust Coding inclui 4 aulas no total.
O que vou aprender em “Compartilhando com Arc e Mutex”?
Altere o estado compartilhado com segurança. Você pratica Learn Rust Coding com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Learn Rust Coding?
Nenhuma experiência prévia é necessária. Learn Rust Coding no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Compartilhando com Arc e Mutex”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Learn Rust Coding?
Sim. Cada aula de Learn Rust Coding inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Criando threads
- Movendo dados para threads
- Compartilhando com Arc e Mutex
- Unindo threads e reunindo resultados