- Tinitiyak ng kalawang ang kaligtasan ng memorya sa pagsasama-sama sa pamamagitan ng pagmamay-ari, paghiram, at habang-buhay, nang hindi gumagamit ng pangongolekta ng basura.
- Ang uri ng system at mga panuntunan sa pag-alyas ay nagbibigay-daan sa concurrency nang walang data race gamit ang mga mutex, channel, at smart pointer.
- Pinapasimple ng cargo, crates.io, at isang aktibong ecosystem ang pamamahala ng dependency, compilation, pagsubok, at deployment.
- Ang pag-unawa sa mga struct, enum, Option, at Resulta ay susi sa paghawak ng mga error at pagmomodelo ng ligtas na data sa mga kasabay na application.
Ang kalawang ay naging isa sa mga wikang iyon Ang bawat developer ng system ay paulit-ulit na naririnig ito.Ito ay kasing bilis ng C at C++, ngunit may halos nakakahumaling na pagtutok sa kaligtasan ng memorya at maayos na pagkakatugma. Ito ay hindi lamang walang laman na marketing: ang disenyo nito ay umiikot sa compiler na nagde-detect ng mga error sa oras ng pag-compile—mga error na makikita mo lang sa ibang mga wika kapag nasa produksyon na ang system... o kapag nag-crash ito.
Kung interesado kang maunawaan Paano nakakamit ni Rust ang ligtas na memorya nang walang pagkolekta ng basura at pagkakatugma nang walang takot sa pagtakbo ng dataAng tutorial na ito ay para sa iyo. Sasaklawin namin ang lahat mula sa mga pangunahing kaalaman ng wika at ecosystem nito hanggang sa mga pangunahing konsepto tulad ng pagmamay-ari, paghiram, mga uri ng tambalan, mga tool tulad ng Cargo, at kahit na tingnan ang mga atomic na uri at pag-lock mula sa isang mas madaling ma-access na pananaw para sa mga bago sa concurrency, lahat ay may pagtuon sa seguridad at pagganap.
Rust Tutorial: Performance, Memory Safety, at Concurrency
Ang Rust ay isang programming language programming pangkalahatang layunin at multi-paradigm, na idinisenyo para sa low-level system programming gayundin para sa mga high-level na proyektomula sa OSMula sa mga engine at browser ng laro hanggang sa mga serbisyo sa web na may mataas na pagganap, nagmula ito sa Mozilla na may layuning pahusayin ang seguridad ng software, lalo na sa mga sensitibong bahagi tulad ng isang browser engine.
Ang pagtukoy sa katangian nito ay iyon ginagarantiyahan ang kaligtasan ng memorya sa oras ng pag-compile nang hindi gumagamit ng basurero. Sa halip, gumagamit si Rust ng isang sistema ng pagmamay-ari at isang borrow checker na sumusubaybay sa tagal ng buhay ng bawat halaga at mga reference nito. Iniiwasan nito ang mga klasikong problema tulad ng mga nakabitin na pointer, buffer overflow, o memory leaks nang hindi nangangailangan ng awtomatikong pagbibilang ng reference o pangongolekta ng basura.
Higit pa rito, ang Rust ay idinisenyo upang gawing mas madali ligtas na pagkakaisaPinipigilan ng uri at modelo ng pagmamay-ari nito ang mga karera ng data sa pagitan ng mga thread, kahit man lang habang nananatili sa ligtas na Rust code. Nangangahulugan ito na maraming mga mapanganib na sitwasyon ang nakita sa oras ng pag-compile, bago ang isang linya ay naisakatuparan.
Para sa lahat ng mga kadahilanang ito, gusto ng malalaking kumpanya Dropbox, Microsoft, Amazon o Google Pinagtibay nila ang Rust sa mga kritikal na bahagi ng kanilang imprastraktura. At hindi nagkataon lang na nanguna ito sa mga botohan sa Stack Overflow sa loob ng maraming taon bilang isa sa mga "pinakamahal" na wika ng mga developer: pinagsasama nito ang C++-style na performance sa isang modernong toolset (Cargo, crates.io) at isang napakaaktibong komunidad, ang tinatawag na Rustaceans.
Pangunahing konsepto: programming language, mga uri at memorya
Bago pag-aralan ang mga detalye ng seguridad at pagkakatugma ng memorya, sulit na linawin ang ilang pangkalahatang konsepto na lumilitaw sa kabuuan oras Kapag nagtatrabaho sa Rust, lalo na kung nanggaling ka sa ibang wika o nagsisimula pa lang mag-program.
Ang isang programming language ay, sa huli, isang hanay ng mga panuntunan at istruktura na nagbibigay-daan sa iyong ilarawan ang mga algorithm at ibahin ang mga ito sa mga executable na programa. Nag-compile ang Rust sa native machine code gamit ang compiler nito rustcSamakatuwid, ang pagganap na nakukuha mo ay karaniwang katumbas ng C at C++.
Ang pamamahala ng memorya ay ang proseso kung saan ang isang programa naglalaan at naglalabas ng mga bloke ng memorya habang tumatakboAng mga error sa lugar na ito ay kadalasang nakamamatay: memory leaks (hindi naipalabas ang hindi nagamit na memorya), data corruption mula sa out-of-bounds na pagsusulat, o paggamit ng memory pagkatapos na ito ay mapalaya. Tinutugunan ito ng kalawang sa isang napakalakas na uri ng sistema at mga pormal na panuntunan para sa pagmamay-ari, paghiram, at habambuhay.
Nagtatampok din ang kalawang ng mga termino tulad ng matalinong uri at payoInilalarawan ng isang uri kung anong uri ng data ang iniimbak ng isang variable (mga integer, float, string, istruktura, atbp.) at kung paano ito mamanipula. Mga matalinong payo (halimbawa, Box, Rc y Arc) ay mga istrukturang nagpapaloob sa mga address ng memorya at nagdaragdag ng dagdag na lohika upang ligtas na pamahalaan ang mga mapagkukunan, tulad ng pagbibilang ng mga nakabahaging sanggunian o paglipat ng mga halaga sa heap.
Sa larangan ng kompetisyon, ang mga konsepto tulad ng kundisyon ng lahi, mutex, at channel Nagiging kailangang-kailangan ang mga ito: nangyayari ang isang kundisyon ng lahi kapag maraming thread ang nag-access at binago ang isang nakabahaging mapagkukunan nang sabay-sabay nang walang wastong koordinasyon; tinitiyak ng mutex (mutual exclusion) na isang thread lang ang pumapasok sa kritikal na seksyon sa isang pagkakataon; at mga channel ay nagbibigay-daan sa mga mensahe na maipadala sa pagitan ng mga thread nang hindi direktang nagbabahagi ng memorya.
Bakit matuto ng Rust: Memory safety at walang takot na pagkakasabay
Nakuha ni Rust ang katanyagan nito dahil nag-aalok ito tatlong napakahalagang haligi para sa modernong programmingPagganap, seguridad, at kasalukuyang mga tool. Tingnan natin kung bakit napakahalaga ng mga puntong ito.
Tungkol sa performance, Rust direktang nag-iipon sa mga katutubong binary nang hindi nangangailangan ng virtual machine o interpreter. Nilalayon ng modelong zero-cost abstractions na matiyak na ang mga abstraction na may mataas na antas ay hindi nagdaragdag ng overhead sa runtime. Samakatuwid, ito ay perpekto para sa pag-unlad ng system. laro, mga bahagi ng browser o mga microservice na mababa ang latency.
Nakabatay ang seguridad sa memorya nito sistema ng pagmamay-ari at pautangWalang tagakolekta ng basura, ngunit alam ng tagatala kung sino ang nagmamay-ari ng bawat mapagkukunan, kung kailan hindi na ito kailangan, at kung kailan ito mailalabas. Pinipigilan nito ang mga leaks, nakabitin na mga pointer, at marami sa mga error na tradisyonal na ginawang mapanganib ang C at C++ programming.
Sa lugar ng kumpetisyon, hinahabol ni Rust ang karaniwang tinatawag "pagkakasundo nang walang takot"Ang uri ng system mismo ay pumipigil sa mga ugat ng data mula sa umiiral sa secure na code. Kung gusto mong magbahagi ng nababagong data sa pagitan ng mga thread, kakailanganin mong gumamit ng mga naaangkop na primitive gaya ng Mutex, RwLock o Arc, at titiyakin ng compiler na iginagalang ang mga alituntunin ng aliasing at mutability.
Ang karanasan sa pag-unlad ay pinahusay ng mga modernong kasangkapan tulad ng KargaNagtatampok ito ng pinagsama-samang manager ng package at bumuo ng imprastraktura, at isang malawak na ecosystem ng mga aklatan (crates) na sumasaklaw sa lahat mula sa asynchronous networking (Tokyo) hanggang sa mga web frameworks (Actix, Rocket, Axum). Ang lahat ng ito ay sinusuportahan ng isang bukas, prolific, at medyo matiyagang komunidad, lalo na para sa mga nagsisimula.
Pag-install at mahahalagang tool: rustup, rustc at Cargo
Upang isulat at patakbuhin ang iyong mga unang programa sa Rust, ang karaniwang paraan upang magsimula ay sa pamamagitan ng pag-install ng opisyal na toolchain gamit kalawangin (tingnan ang Kumpletuhin ang pagpapakilala sa Rust), isang simpleng installer at tagapamahala ng bersyon na gumagana sa lahat ng pangunahing operating system.
may kalawangin Maaari kang mag-install, mag-update, at magpalipat-lipat sa iba't ibang bersyon ng Rust (stable, beta, gabi-gabi) nang walang sinisira. Pumunta lang sa opisyal na pahina ng Rust tools at sundin ang mga hakbang para sa iyong system. Kapag na-install, magiging available ang compiler. rustc, ang tagapamahala ng proyekto cargo at ang kanyang sarili rustup sa iyong pandulo.
ang compiler rustc Ito ang nagpapabago sa iyong source code sa mga executable na binary o library. Bagama't maaari mo itong i-invoke nang direkta gamit ang comandos bilang rustc main.rsSa pagsasagawa, halos palaging gagawin mo ang Cargo, na humahawak sa mga tawag sa rustc gamit ang mga tamang pagpipilian.
Ang sentral na tool ng daloy ng trabaho ay KargaSa ilang utos lamang, maaari kang lumikha ng mga bagong proyekto, pamahalaan ang mga dependency, mag-compile, magpatakbo, sumubok, at mag-publish ng mga pakete sa crates.io. Ang ilang karaniwang ginagamit na mga pangunahing utos ay: cargo new, cargo build, cargo run, cargo test y cargo check, na sumusuri sa code nang hindi gumagawa ng panghuling executable, perpekto para sa mabilis na pag-detect ng mga error.
Kung gusto mong mag-tinker nang hindi nag-i-install ng kahit ano, Palaruan ng kalawang (ang opisyal na online executor) at mga platform tulad ng Replit ay nagbibigay-daan sa iyo na magsulat at magpatakbo ng maliliit na piraso ng code mula sa browser, perpekto para sa pag-eksperimento sa mga halimbawa ng memory at concurrency nang hindi kinakailangang i-set up ang buong kapaligiran.
Ang iyong unang programa: Hello, Rust, at basic flow
Ang klasikong paraan upang magsimula ng isang pag-uusap sa anumang wika ay sa sikat na "Hello, world." Sa Rust, isang file main.rs hindi bababa sa maaaring maglaman ng isang bagay na kasing simple ng isang function main na nagpi-print ng string sa screen.
Ang susing salita fn ay nagpapahiwatig na kami ay tumutukoy sa isang function, at main Ito ang entry point ng programa. Ang code block ng function ay napupunta sa loob ng curly braces. Upang sumulat sa console, gamitin ang macro println!, na tumatanggap ng literal na string (o isang template na may mga bookmark) at ipinapadala ito sa karaniwang output na nagtatapos sa isang newline na character.
Kung nag-compile ka nang direkta sa rustc main.rs, makakakuha ka ng executable binary (halimbawa, main o main.exe (depende sa sistema). Kapag pinatakbo mo ito, makikita mo ang mensahe sa terminal. Ngunit ang idiomatic na paraan upang makatrabaho si Rust ay ang hayaan si Cargo na manguna sa proyekto.
may cargo new nombre_proyecto Awtomatikong nagagawa ang istraktura ng folder gamit ang a src/main.rs handa na sa isang "Hello, world" at isang file Cargo.toml na naglalaman ng metadata at mga dependency sa hinaharap. Mula doon, cargo run i-compile at patakbuhin ang binaryat nagre-recompile lang ito kapag nakakita ng mga pagbabago.
Ang ganitong paraan ng pagtatrabaho ay hindi lamang maginhawa, ngunit nasanay ka nitong gamitin ang karaniwang Rust ecosystem mula sa simula, na lubhang kapaki-pakinabang kapag nagsimula kang magdagdag ng mga crates para sa concurrency, networking, pagsubok, o anumang kailangan mo.
// Idineklara namin ang pangunahing function: program entry point fn main() { // Ginagamit namin ang println! macro para mag-print ng text sa console println!("Hello, world!"); }
Mga variable, pagbabago, at pangunahing uri ng data
Sa Rust, idineklara ang mga variable gamit ang keyword let, at bilang default ay hindi nababagoSa madaling salita, kapag nagtalaga ka sa kanila ng isang halaga, hindi mo ito mababago maliban kung tahasan mong ideklara ito bilang nababago sa mut.
Ang kawalan ng pagbabago bilang default ay nakakatulong na maiwasan ang banayad na mga error sa lohika, lalo na sa kasabay na mga programa kung saan maraming mga thread ang maaaring gustong baguhin ang parehong halaga. Kung kailangan mong baguhin ito, sumulat ka ng isang bagay tulad ng let mut contador = 0;Mula doon maaari kang magtalaga ng mga bagong halaga sa contador.
Pinapayagan din ng kalawang ang tinatawag na aninoMaaari kang magdeklara ng bagong variable na may parehong pangalan sa loob ng parehong saklaw, na itinatago ang nauna. Hindi ito katulad ng pag-mutate, dahil lumilikha ka ng bagong halaga (na maaaring maging ibang uri). Halimbawa, maaari kang mag-convert mula sa isang string patungo sa isang integer gamit ang parehong pangalan, hangga't ito ay isang bagong deklarasyon na may let.
Ang sistema ng uri ng kalawang ay static, na nangangahulugang iyon Ang uri ng bawat variable ay kilala sa compilationGayunpaman, medyo makapangyarihan ang uri ng hinuha: kung isusulat mo let x = 5;Ipinapalagay ng compiler na ito ay a i32 Maliban kung sasabihin mo ito kung hindi man. Maaari kang magdagdag ng mga tala tulad ng let x: i64 = 5; kapag gusto mong maging tahasan.
Kabilang sa mga available na uri ng scalar ay ang mga signed at unsigned integers (i8, u8, i32, atbp.), ang mga lumulutang (f32, f64), ang mga Boolean (bool) at mga Unicode na character (char). Ang mga simpleng uri na ito ay karaniwang mura upang kopyahin at marami ang nagpapatupad ng katangian Copyna nangangahulugan na kapag itinalaga mo ang mga ito o ipinasa mo sila sa isang function, sila ay kinokopya sa halip na ilipat.
Mga String sa Rust: &str at String
Ang paghawak ng text sa Rust ay maaaring medyo nakakalito sa simula dahil malinaw na nakikilala nito ang pagitan chain "slices" at proprietary chainAng dalawang pangunahing piraso ay &str y String.
Un &str ay isang hiwa ng hindi nababagong kadenaIsang view ng isang UTF-8 byte sequence na nakaimbak sa isang lugar. Kasama sa mga karaniwang halimbawa ang mga literal na tulad ng "Hola"na nasa uri &'static str (Ang mga ito ay umiiral para sa buong buhay ng programa at naka-embed sa binary.) Ang mga hiwa ay hindi pagmamay-ari ng data; tinuturo lang nila ito.
String, sa kabilang banda, ay a sariling string, nababago at naka-host sa heapMaaari itong baguhin ang laki, pinagsama-sama, ipasa sa pagitan ng mga function sa pamamagitan ng paglipat ng property nito, atbp. Madalas itong ginagamit kapag gusto mong bumuo ng dynamic na text o iimbak ito nang pangmatagalan sa loob ng mga istruktura.
Sa maraming mga sitwasyon, magbabago ka sa pagitan ng isa at ng isa: halimbawa, gagawa ka ng a String::from("hola") mula sa isang hiwao hihiram ka ng a &str isang String sa pamamagitan ng pagpasa ng mga sanggunian sa mga function na kailangan lamang basahin.
Ang paghihiwalay na ito sa pagitan ng pagmamay-ari at hiniram na data ay susi sa pamamahala ng memorya at umaabot sa iba pang wika: ang mga koleksyon, istruktura, at mga enum ay sumusunod sa parehong mga ideya kung sino ang nagmamay-ari at kung sino lamang ang tumitingin.
Mga function, daloy ng kontrol, at komento
Ang mga function sa Rust ay tinukoy sa fn at payagan ang programa na maisaayos sa magagamit muli na mga lohikal na yunit. Tinutukoy ng bawat function ang uri ng mga parameter nito at ang uri ng pagbabalik nito sumusunod sa isang arrow ->Kung wala itong naibalik na makabuluhan, ang unitary type ay ipinapalagay. ().
Ang isang mahalagang detalye ay ang huling expression sa isang function (o anumang block) na walang semicolon ay kinuha bilang ang implicit return value. Maaari mong gamitin return para sa maagang pagbabalikNgunit sa idiomatic code, madalas mong iwanan ang huling expression nang wala. ;.
Ang control flow ay pinangangasiwaan ng mga classic if/elsemga loop loop, while y forSa kalawang, if Ito ay isang expression na nagbabalik ng isang halagapara magamit mo ito nang direkta sa a letsa kondisyon na ibabalik ng mga sangay ang parehong uri. Mga loop for Karaniwang umuulit ang mga ito sa mga saklaw o mga iterator ng koleksyon at ito ang inirerekomendang opsyon sa halip na mga manu-manong index.
Upang idokumento ang code at gawing mas madali ang buhay para sa sinumang susunod (kabilang ang iyong sarili sa isang buwan), maaari mong gamitin mga komento sa linya kasama ang // o i-block sa /* ... */Bilang karagdagan, nag-aalok ang Rust ng mga komento sa dokumentasyon na may /// na nagiging mga nabuong dokumento, bagama't mas akma iyon sa malalaking proyekto.
Pagmamay-ari, pagpapahiram, at habambuhay: ang pundasyon ng seguridad ng memorya
Dito tayo nakarating sa puso ng modelo ng memorya ni Rust: ang sistema ng pagmamay-ari, paghiram, at habang-buhayTinitiyak ng mga panuntunang ito na ang mga sanggunian ay palaging wasto at ang memorya ay ligtas na nailalabas nang walang naipon na basura.
Ang mga pangunahing alituntunin ng pagmamay-ari ay simpleng sabihin, bagama't maaaring mahirap i-internalize ang mga ito sa simula: Ang bawat halaga ay may iisang may-ari.Maaari lamang magkaroon ng isang may-ari sa isang pagkakataon; at kapag ang may-ari ay umalis sa saklaw nito, ang halaga ay nawasak at ang memorya nito ay inilabas. Nalalapat ito, halimbawa, sa a String: sa pagkumpleto ng bloke kung saan ito idineklara, awtomatiko itong na-invoke drop na nagpapalaya sa heap memory.
Kapag nagtalaga ka ng wastong halaga sa isa pang variable o ipinasa ito ayon sa halaga sa isang function, ang property ay ililipat. Ibig sabihin nito ang orihinal na variable ay titigil na maging wasto pagkatapos ng paglipatIniiwasan ng mga semantika ng paggalaw na ito ang mga dobleng paglabas, dahil walang dalawang may-ari na sumusubok na ilabas ang parehong mapagkukunan.
Upang payagan ang maraming bahagi ng programa na ma-access ang parehong halaga nang hindi binabago ang pagmamay-ari, ipinakilala ni Rust ang mga sanggunian at paghiram. Kapag nanghiram ka, gagawa ka ng reference &T (hindi nababago) o &mut T (nababago) sa halaga nang hindi inililipat ang pagmamay-ari. Ang loan ay nililimitahan ng mga panuntunan ng loan verifier., na nagsusuri na ang mga sanggunian ay hindi lumalampas sa data na kanilang itinuturo at na ang mga nababago at nakabahaging pag-access ay hindi mapanganib na pinaghalo.
Ang mga alituntunin ng pautang ay maaaring buod tulad ng sumusunod: sa anumang oras, maaari kang magkaroon maramihang hindi nababagong sanggunian sa isang halaga, o isang solong nababagong sanggunianNgunit hindi pareho sa parehong oras. Inaalis nito ang mga kundisyon ng lahi sa ibinahaging memorya: maaaring mayroong maraming mga mambabasa, o mayroong isang nakahiwalay na manunulat; hindi kailanman sabay-sabay na mga mambabasa at manunulat sa parehong data sa parehong instant.
Mga composite na uri: mga struct, enum, at matalinong pointer
Nagbibigay ang Rust ng ilang paraan upang pagpangkatin ang mga nauugnay na data sa mas mayayamang istruktura, simula sa mga istrukturaBinibigyang-daan ka ng isang struct na tukuyin ang isang pasadyang uri na may pinangalanang mga patlang, halimbawa isang user na may email, pangalan, katayuan ng aktibidad at counter sa pag-login.
Upang lumikha ng isang halimbawa ng isang istraktura, punan mo ang lahat ng mga patlang nito, at maaari mong markahan ang variable na naglalaman nito bilang nababago upang baguhin ang mga halaga nito sa ibang pagkakataon. Mayroon ding struct update syntax, na nagbibigay-daan sa iyong bumuo ng bagong instance sa pamamagitan ng muling paggamit ng ilang field mula sa isang umiiral na. ..otro_struct.
Los enums Ang mga ito ay isa pang mahalagang haligi: pinapayagan ka nitong tukuyin ang isang uri na maaaring isa sa ilang posibleng variant, bawat isa ay may sarili nitong nauugnay na data o wala nito. Ang isang klasikong halimbawa ay isang enum para sa mga IP address, na may isang variant V4 na nag-iimbak ng apat na octet at isa pa V6 na nag-iimbak ng string na may IPv6 notation.
Kasama sa karaniwang aklatan ng Rust ang dalawang napakahalagang enum: Option<T> y Result<T, E>Ang una ay kumakatawan sa presensya o kawalan ng isang halaga (isang bagay o wala), at ginagamit upang maiwasan ang mga null pointer; ang pangalawang modelo ng mga operasyon na maaari ibalik ang isang tamang resulta o isang error, na nangangailangan na ang paghawak ng error ay tahasan at secure.
Upang pamahalaan ang dynamic na memorya at magbahagi ng data, mayroon si Rust matalinong mga payo bilang Box<T>, na naglilipat ng halaga sa heap at nagpapanatili ng natatanging pagmamay-ari; Rc<T>, isang nakabahaging bilang ng sanggunian para sa mga single-threaded na kapaligiran; at Arc<T>, katulad ng Rc ngunit ligtas para sa maraming mga thread. Ang paggamit ng mga ito ng tama ay mahalaga kapag pinagsasama ang dynamic na memorya sa concurrency.
Cargo at ang Crates Ecosystem
Ang Cargo ay ang pandikit na humahawak sa Rust ecosystem na magkasama: namamahala sa compilation, dependencies, at lifecycle ng proyektoAng bawat proyekto ay may file Cargo.toml na gumaganap bilang isang manifest, na nagdedeklara ng pangalan, bersyon, edisyon ng wika, at mga panlabas na dependency.
Seksyon Binibigyang-daan ka ng file na ito na ilista ang mga third-party na crates kasama ng kanilang mga bersyon. Kapag tumakbo ka cargo build o cargo runAwtomatikong dina-download ng Cargo ang mga crates na ito mula sa crates.io, kino-compile ang mga ito, at ini-link ang mga ito sa iyong proyekto. Napakadaling idagdag, halimbawa, mga generator ng random na numero, web framework, o mga cryptographic na library.
Kabilang sa mga pinakakaraniwang utos ay cargo new upang simulan ang mga binary na proyekto o cargo new --lib para sa mga aklatan; cargo build mag-compile sa debug mode; cargo build --release upang makakuha ng isang optimized, production-oriented na bersyon; at cargo test upang patakbuhin ang baterya ng mga pagsubok.
cargo check Ito ay nararapat na espesyal na banggitin: pinagsama-sama nito ang code sa isang intermediate point nang hindi bumubuo ng isang binary, na ginagawa itong maging napakabilis sa pag-detect ng mga error sa compilationIto ay perpekto para sa mabilis na pag-ulit habang ang borrow checker ay nagtuturo ng mga problema sa mga pag-aari, sanggunian, at habang-buhay.
Salamat sa ecosystem na ito, karaniwan nang buuin ang iyong mga proyekto bilang maliit, mahusay na tinukoy na mga crates, pagbabahagi ng code sa pagitan ng mga ito at muling paggamit ng mga solusyon na ginawa ng komunidad. Para sa advanced na concurrency, halimbawa, magkakaroon ka ng mga crates tulad ng Tokio para sa asynchronous na programming o crossbeam para sa mataas na pagganap ng sabay-sabay na mga istruktura ng data.
Concurrency sa Rust: mga thread, mutex, channel, at atomics
Ang concurrency ay isa sa mga dahilan kung bakit nagkakaroon ng labis na interes ang Rust: pinapayagan ka nitong samantalahin ang mga multi-core na processor. nang hindi nahuhulog sa mga tipikal na error ng mga thread at nakabahaging memoryaKung ito ang iyong unang pagkakataon na lumapit sa mga paksang ito, makatutulong na makilala ang ilang mga konsepto.
Kasama sa concurrency ang pagsasagawa ng maraming gawain na magkakapatong sa oras, alinman sa isa o maraming core. Sa Rust, maaari kang lumikha ng mga thread ng system upang gumanap nang magkatulad, at ginagabayan ka ng wika upang matiyak na ligtas ang pagbabahagi ng data sa pagitan ng mga ito. Ang isang klasikong error ay ang kundisyon ng lahi, kung saan ang dalawang thread ay nag-a-access at nagbabago ng data nang sabay-sabay, at ang resulta ay depende sa utos ng pagpapatupad—isang bagay na napakahirap i-debug.
Upang i-coordinate ang pag-access sa nakabahaging data, umaasa si Rust sa mga primitive gaya ng mutexna ginagarantiyahan ang pagbubukod sa isa't isa: isang thread lamang ang maaaring pumasok sa kritikal na seksyon sa isang pagkakataon. Sa kumbinasyon ng Arc<T> Upang ibahagi ang pagmamay-ari sa pagitan ng mga thread, posibleng bumuo ng mga nakabahaging istruktura ng data na sumusunod sa mga panuntunan ng pagmamay-ari at paghiram.
Ang isa pang karaniwang paraan ng inter-threaded na komunikasyon, na lubos na hinihikayat sa Rust, ay ang paggamit ng pagpasa ng mensahe mga channelAng channel ay may pagpapadala ng dulo at pagtanggap ng dulo; ang mga thread ay nagpapasa ng mga mensahe (mga halaga) sa pamamagitan nito, na binabawasan ang paggamit ng nababagong ibinahaging memorya at pinapasimple ang pangangatwiran tungkol sa estado ng system.
Kapag mas malalim ang iyong pinag-aralan sa mababang antas ng pagkakatugma, lilitaw ang sumusunod: mga uri ng atomicNaa-access ang mga variable ng atom sa pamamagitan ng mga operasyon na hindi mahahati mula sa pananaw ng thread. Nagbibigay-daan ito para sa pagpapatupad ng mga nakabahaging counter, mga flag ng estado, mga pila na walang lock, at higit pa. Ang pag-master ng mga atomic variable ay nangangailangan ng pag-unawa sa mga modelo ng memorya at mga command sa pag-access, kaya maraming mga developer ang gustong magsimula sa mga mutex at channel bago pag-aralan ang mga detalyeng ito.
Mga unang hakbang at mapagkukunan para sa pag-aaral ng concurrency at atomics
Kung pumapasok ka sa arena na walang paunang karanasan, ang pinakamatalinong paraan ng pagkilos ay bumuo ng matibay na pundasyon ng mga pangkalahatang konsepto bago harapin ang mga advanced na tool tulad ng mga atomic na uri ng Rust. Ang mga aklat tulad ng "Programming Rust" ay nag-aalok ng unti-unting pagpapakilala, ngunit normal para sa mga gawang nakatuon sa mga uri ng atomic at mga lock na mukhang siksik sa simula.
Para sa higit na kadalian, ipinapayong pamilyar muna ang iyong sarili Mga tradisyunal na thread, kapwa pagbubukod, at pagpasa ng mensahe sa kalawang. Maglaro ng mga halimbawa ng std::thread, std::sync::Mutex, std::sync::Arc at mga channel ng std::sync::mpsc Tinutulungan ka nitong maunawaan kung paano ginagabayan ka ng compiler at kung anong mga error ang iniiwasan nito.
Kasabay nito, lubos na inirerekomendang suriin ang mga panimulang mapagkukunan sa concurrency sa pangkalahatan, kahit na hindi sila nakatuon sa Rust: pag-unawa kung ano ang mga kondisyon ng lahi, kung ano ang ibig sabihin ng pagharang, kung ano ang ipinahihiwatig ng shared memory kumpara sa pagpasa ng mensahe, at kung paano ginagamit ang mga lock. Kapag naging natural na sa iyo ang mga konseptong iyon, hindi na magiging "black magic" ang atomic physics. at sila ay naging isa pang kasangkapan, isa lamang napaka-pinong.
Kapag bumalik ka sa mas advanced na mga teksto tungkol sa atomics at lock sa Rust, magiging mas madaling sundin ang pangangatwiran kung naiintindihan mo na kung anong problema ang sinusubukang lutasin ng bawat konstruksyon: mula sa isang simpleng thread-safe counter hanggang sa mga istrukturang walang lock na nagpapaliit ng pagtatalo.
Sa huli, nag-aalok ang Rust ng parehong high-level primitives at very low-level na mga tool, at ang susi ay palaging piliin ang pinakaligtas na antas ng abstraction na lumulutas sa iyong problema, gamit ang atomic code. unsafe kapag ito ay tunay na nagdaragdag ng halaga at lubos mong nauunawaan ang mga implikasyon nito.
Ang buong ecosystem na ito ng mga uri, pagmamay-ari, paghiram, crates, tool, at concurrency primitives ay pinagsama upang mag-alok ng isang wika kung saan isusulat mabilis, matatag at mapanatili ang softwarePinaliit nito ang maraming uri ng mga error na dati nang sinalanta ang programming ng system. Habang nagsasanay ka sa maliliit na proyekto, mga pagsasanay tulad ng Rustlings, at opisyal na dokumentasyon, ang mga konseptong ito ay magmumula sa tila mahigpit na mga panuntunan hanggang sa pagiging isang kaalyado na nagbabala sa iyo bago umabot sa produksyon ang problema.
Masigasig na manunulat tungkol sa mundo ng mga byte at teknolohiya sa pangkalahatan. Gustung-gusto kong ibahagi ang aking kaalaman sa pamamagitan ng pagsusulat, at iyon ang gagawin ko sa blog na ito, ipakita sa iyo ang lahat ng mga pinaka-kagiliw-giliw na bagay tungkol sa mga gadget, software, hardware, teknolohikal na uso, at higit pa. Ang layunin ko ay tulungan kang mag-navigate sa digital na mundo sa simple at nakakaaliw na paraan.