Înțelegeți abordarea lui Rust față de concurență, care se bazează pe conceptul de „concurență fără teamă”.
Concurența este capacitatea unui program de a executa mai multe sarcini simultan pe același nucleu CPU. Sarcinile concurente rulează și se completează în timp suprapus fără ordine specificată, spre deosebire de paralelism, unde diverse sarcini sau subsarcini ale aceleiași sarcini rulează în același timp pe hardware cu multiple procesoare.
Rust se remarcă prin caracteristicile sale de performanță și suportul pentru concurență într-un mod sigur și eficient. Abordarea lui Rust asupra concurenței se bazează pe conceptul de „concurență fără teamă”, în care limbajul urmărește să faciliteze scrierea în siguranță. cod concurent prin sistemul său de proprietate și împrumut, care impune reguli stricte în timpul compilării pentru a preveni urmărirea datelor și pentru a asigura memoria Siguranță.
Înțelegerea concurenței în Rust
Rust oferă mai multe primitive de concurență pentru scrierea de programe concurente, inclusiv fire de execuție, transmitere de mesaje, mutexuri, tipuri atomice și asincron/așteptare pentru programarea asincronă.
Iată o prezentare generală a primitivelor de concurență ale Rust:
- Fire: Rugina oferă a std:: fir modul în biblioteca sa standard pentru crearea și gestionarea firelor de execuție. Puteți genera fire noi cu thread:: spawn funcţie. The thread:: spawn ia o închidere care conține codul pentru execuție. De asemenea, puteți rula fire care pot rula în paralel, iar Rust oferă primitive de sincronizare pentru a coordona execuția lor. Verificatorul de împrumuturi se asigură că referințele nu conduc la comportamente neașteptate.
- Trecere mesaj: Modelul de concurență al Rust acceptă trecerea mesajelor între fire. Veți folosi canalele implementate prin intermediul std:: sincronizare:: mpsc modul pentru transmiterea mesajelor. Un canal este format dintr-un transmițător (Expeditor) și un receptor (Receptor). Thread-urile pot trimite mesaje prin transmițător și le pot primi prin receptor. Aceasta oferă o modalitate sigură și sincronizată de comunicare între fire.
- Mutexuri și tipuri atomice: Rust oferă primitive de sincronizare, inclusiv mutexuri (std:: sync:: Mutex) și tipuri atomice (std:: sync:: atomic), pentru a asigura accesul exclusiv la partajarea datelor. Mutexurile permit mai multor fire de execuție să acceseze date simultan, prevenind în același timp cursele de date. Tipurile atomice oferă operații atomice asupra datelor partajate, cum ar fi incrementarea unui contor, fără a necesita blocarea explicită.
- Async/Await și Futures: Al lui Rust asincron/așteaptă sintaxa oferă funcționalitate pentru scrierea codului asincron pe care îl puteți executa concomitent. Programele asincrone se ocupă eficient de sarcinile legate de I/O, permițând programelor să efectueze alte sarcini în timp ce așteaptă alte operațiuni I/O. Al lui Rust asincron/așteaptă sintaxa se bazează pe futures și le puteți alimenta cu ajutorul async-std sau tokio biblioteci runtime.
Firele de rugină sunt ușoare, iar absența timpului de rulare le face bine potrivite pentru aplicații de înaltă performanță. Primitivele de concurență Rust se integrează perfect cu mai multe biblioteci și cadre pentru diferite nevoi de concurență.
Cum să utilizați firele de spawn în Rust
Vei folosi std:: fir modul pentru a genera fire. The std:: thread:: spawn funcția vă permite să creați un fir nou care va rula concomitent cu firul principal sau cu orice alte fire existente în programul dvs.
Iată cum puteți crea un fir cu std:: thread:: spawn funcţie:
utilizare std:: fir;
fnprincipal() {
// Apare un nou thread
lăsa thread_handle = thread:: spawn(|| {
// Codul executat în noul thread merge aici
println!("Salut din noul thread!");
});// Așteptați ca firul generat să se termine
thread_handle.join().unwrap();
// Codul executat în firul principal continuă aici
println!("Bună ziua din firul principal!");
}
The principal funcția creează un fir nou cu thread:: spawn funcția prin trecerea unei închideri care conține codul pentru execuție în fir (în acest caz, închiderea este o funcție anonimă). Închiderea afișează un mesaj care indică faptul că noul fir rulează.
The a te alatura metoda pe thread_handle permite firului principal să aștepte până la finalizarea execuției firului generat. Sunând a te alatura, funcția asigură că firul principal așteaptă finalizarea firului generat înainte de a continua.
Puteți genera mai multe fire și puteți utiliza o buclă sau orice alta Structura de control al ruginii pentru a crea mai multe închideri și a genera fire pentru fiecare.
utilizare std:: fir;
fnprincipal() {
lăsa num_threads = 5;lăsamut thread_handles = vec![];
pentru i în0..num_threads {
lăsa thread_handle = thread:: spawn(mișcare || {
println!(„Salut din firul {}”, i);
});
mâner_file.push (mâner_file);
}pentru mâner în fire_handle {
handle.join().unwrap();
}
println!("Toate firele s-au terminat!");
}
Bucla for generează cinci fire de execuție, fiecare atribuit unui identificator unic i cu variabila buclă. Închiderile captează valoarea de i cu mișcare cuvânt cheie de evitat probleme de proprietate, si fire_manere vector stochează firele pentru mai târziu în a te alatura buclă.
După ce a generat toate firele, the principal funcția iterează peste fire_manere vector, apeluri a te alatura pe fiecare mâner și așteaptă ca toate firele să se execute.
Transmiterea de mesaje prin canale
Puteți trece mesaje prin fire cu canale. Rust oferă funcționalitate pentru transmiterea mesajelor în std:: sincronizare:: mpsc modul. Aici, mpsc înseamnă „multiple producer, single consumer” și permite comunicarea între mai multe fire prin trimiterea și primirea de mesaje prin canale.
Iată cum implementați mesajul care trece prin canalele de comunicare inter-thread în programele dvs.:
utilizare std:: sync:: mpsc;
utilizare std:: fir;fnprincipal() {
// Creați un canal
lăsa (emițător, receptor) = mpsc:: canal();// Generați un fir
thread:: spawn(mișcare || {
// Trimite un mesaj prin canal
sender.send("Salut din thread!").unwrap();
});
// Primește mesajul în firul principal
lăsa mesaj_primit = receiver.recv().unwrap();
println!(„Mesaj primit: {}”, mesaj_primit);
}
The principal funcția creează un canal cu mpsc:: canal() care returnează a expeditor si a receptor. The expeditor trimite mesaje către receptor care primește mesajele. The principal funcția continuă să genereze fire de execuție și să mute dreptul de proprietate asupra fișierului Expeditor până la închiderea filetului. În interiorul închiderii cu fir, sender.send() funcția trimite un mesaj prin canal.
The receiver.recv() funcția primește mesajul prin oprirea execuției până când firul de execuție a primit mesajul. The principal funcția imprimă mesajul pe consolă după primirea cu succes a mesajului.
Rețineți că trimiterea unui mesaj prin canal consumă expeditorul. Dacă trebuie să trimiteți mesaje din mai multe fire, puteți clona expeditorul cu sender.clone() funcţie.
În plus, cel mpsc modulul oferă alte metode precum try_recv(), care fără blocare încearcă să primească un mesaj și iter(), care creează un iterator peste mesajele primite.
Trecerea mesajelor prin canale oferă o modalitate sigură și convenabilă de a comunica între fire, evitând în același timp cursele de date și asigurând o sincronizare adecvată.
Modelul de proprietate și împrumut al lui Rust garantează siguranța memoriei
Rust combină proprietatea, împrumutul și verificatorul de împrumut pentru a oferi un cadru de programare robust, sigur și concurent.
Verificatorul de împrumuturi acționează ca o plasă de siguranță, detectând probleme potențiale în timpul compilării, mai degrabă decât să se bazeze pe verificări de rulare sau colectare a gunoiului.