Flytta data till trådar
Använd move-closures korrekt.
Flytta data till trådar är en gratis lektion i Lär dig programmera i Rust på CoddyKit. Detta är lektion 2 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Lär dig programmera i Rust, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Lär dig programmera i Rust innehåller totalt 4 lektioner.
Closures fångar omgivningen
En closure som skickas till thread::spawn kan använda variabler från det omgivande scopet. Som standard lånar Rust dem.
Men en skapad tråd kan leva längre än funktionen som skapade den, så ett vanligt lån är inte säkert. Rust avvisar detta vid kompileringen.
Problemet med lån
Om en tråd lånar en lokal variabel kan kompilatorn inte bevisa att variabeln lever tillräckligt länge. Tråden kan fortsätta köras efter att variabeln har tagits bort.
Koden nedan kompileras inte, eftersom closuren bara lånar data.
use std::thread;
fn main() {
let data = vec![1, 2, 3];
// ERROR: closure may outlive `data`
let h = thread::spawn(|| {
println!("{:?}", data);
});
h.join().unwrap();
}Nyckelordet move
Om ni lägger till move före closuren tvingas den ta ägarskap över de fångade variablerna. De flyttas in i tråden.
Nu äger tråden datan, så det garanteras att den förblir giltig under trådens livstid.
use std::thread;
fn main() {
let data = vec![1, 2, 3];
let h = thread::spawn(move || {
println!("{:?}", data);
});
h.join().unwrap();
}Ägarskapet flyttas ut
När ett värde har flyttats in i en tråd kan det ursprungliga scopet inte längre använda det. Ägarskapet har flyttats.
Om ni försöker använda data i main efter flytten blir det ett kompileringsfel. Tråden är nu ensam ägare.
use std::thread;
fn main() {
let data = vec![1, 2, 3];
let h = thread::spawn(move || println!("{:?}", data));
// println!("{:?}", data); // ERROR: value moved
h.join().unwrap();
}Flytta Copy-typer
Typer som implementerar Copy, till exempel heltal, kopieras i stället för att flyttas. Closuren får sin egen kopia.
Efter att en move-closure har fångat ett tal kan ni därför fortfarande använda originalet i main.
use std::thread;
fn main() {
let n = 42;
let h = thread::spawn(move || {
println!("thread sees {}", n);
});
println!("main still sees {}", n);
h.join().unwrap();
}Send: säker att överföra
En typ kan bara flyttas till en annan tråd om den implementerar traitet Send. Send betyder att det är säkert att överföra ägarskap mellan trådar.
De flesta typer är automatiskt Send. Några, till exempel Rc, är det inte, och kompilatorn avvisar försök att flytta dem.
Rc är inte Send
Rc är en referensräknare för en enda tråd. Räknaren skyddas inte mot samtidiga uppdateringar och är därför inte Send.
Ett försök att flytta en Rc till en tråd misslyckas vid kompileringen. I nästa lektion använder ni i stället Arc.
use std::rc::Rc;
use std::thread;
fn main() {
let r = Rc::new(5);
// ERROR: `Rc<i32>` cannot be sent between threads safely
let h = thread::spawn(move || println!("{}", r));
h.join().unwrap();
}Flytta flera värden
En enda move-closure kan fånga flera variabler samtidigt. Alla flyttas in i tråden.
Det är praktiskt när en arbetsinstruktion behöver både indata och en etikett.
use std::thread;
fn main() {
let label = String::from("sum");
let nums = vec![1, 2, 3, 4];
let h = thread::spawn(move || {
let total: i32 = nums.iter().sum();
println!("{} = {}", label, total);
});
h.join().unwrap();
}Klona före flytten
Om både tråden och huvudfunktionen behöver ett värde ska ni klona det först. Ge den ena kopian till tråden och behåll den andra.
En kloning kopierar datan, så varje sida äger ett oberoende värde.
use std::thread;
fn main() {
let original = String::from("hello");
let for_thread = original.clone();
let h = thread::spawn(move || println!("thread: {}", for_thread));
println!("main: {}", original);
h.join().unwrap();
}Returnera flyttad data
En tråd som äger flyttad data kan returnera den och lämna tillbaka ägarskapet till den överordnade tråden genom join.
Det här mönstret flyttar in data, bearbetar den och flyttar sedan ut resultatet.
use std::thread;
fn main() {
let mut v = vec![3, 1, 2];
let h = thread::spawn(move || {
v.sort();
v
});
let sorted = h.join().unwrap();
println!("{:?}", sorted);
}Varför move krävs
Utan move antar borrow-checkern att closuren lånar. Eftersom skapade trådar inte har någon fast livstid som är bunden till anroparen är lån osäkra.
Nyckelordet move omvandlar lån till ägarskapsöverföringar och uppfyller kravet på 'static i spawn.
Snabbtest
Testa er förståelse av hur data flyttas in i trådar.
Sammanfattning
Ni har lärt er att trådklosurer måste äga de data de använder, vilket uppnås med nyckelordet move.
Att flytta överför ägarskap, medan typer som implementerar Copy kopieras. Traitet Send markerar vad som är säkert att överföra, och Rc implementerar inte Send.
Nästa steg är att dela data mellan trådar med hjälp av Arc och Mutex.
Lär dig Rust med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 39
- Lektioner
- 144
Vanliga frågor
Är lektionen ”Flytta data till trådar” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Lär dig programmera i Rust, inklusive ”Flytta data till trådar”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Lär dig programmera i Rust innehåller totalt 4 lektioner.
Vad lär jag mig i ”Flytta data till trådar”?
Använd move-closures korrekt. Ni övar på Lär dig programmera i Rust med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Lär dig programmera i Rust?
Du behöver inga förkunskaper. Utbildningen i Lär dig programmera i Rust på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.
Hur lång tid tar lektionen ”Flytta data till trådar”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Lär dig programmera i Rust-lektionen?
Ja. Varje Lär dig programmera i Rust-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Skapa trådar
- Flytta data till trådar
- Dela med Arc och Mutex
- Vänta på trådar och samla resultat