Kapsamlı İş Parçacıkları
İş parçacıkları arasında ödünç alma
Kapsamlı İş Parçacıkları, CoddyKit'te ücretsiz bir Learn Rust Coding dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Learn Rust Coding öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Learn Rust Coding kursu toplamda 4 dersten oluşur.
İş Parçacıklarında Ödünç Almanın Sorunu
Normal bir thread::spawn closure'ı 'static olmalıdır: yerel değişkenleri ödünç alamaz, çünkü iş parçacığı bu değişkenlerin sahibi olan işlevden daha uzun yaşayabilir. Bu nedenle move ve Arc ifadelerini sıkça görürsünüz.
Kapsamlı iş parçacıkları bunu, her iş parçacığının kapsam sona ermeden önce tamamlanacağını garanti ederek çözer; böylece yerel verileri ödünç almak güvenli olur.
spawn Neden 'static Gerektirir?
thread::spawn ile oluşturulan iş parçacığı, main veya herhangi bir işlev döndükten sonra çalışmaya devam edebilir. Yerel bir değişkeni ödünç almışsa bu değişken, iş parçacığı onu kullanmaya devam ederken yok edilebilir. Rust bunu derleme zamanında yasaklar ve sahip olunan verileri closure'a taşımanızı zorunlu kılar.
use std::thread;
fn main() {
let nums = vec![1, 2, 3];
// move transfers ownership into the thread
let handle = thread::spawn(move || {
println!("in thread: {:?}", nums);
});
handle.join().unwrap();
}thread::scope ile Tanışma
Rust 1.63'te kararlı hâle getirilen std::thread::scope, iş parçacıklarının yerel değişkenleri ödünç alabileceği bir kapsam oluşturur. Kapsam, içindeki tüm iş parçacıkları tamamlanana kadar bekler; böylece ödünç alınan başvurular hiçbir zaman geçersiz hâle gelemez.
thread::spawn yerine kapsam tutamacı s'yi kullanarak s.spawn(...) ile iş parçacığı oluşturursunuz.
use std::thread;
fn main() {
let data = vec![10, 20, 30];
thread::scope(|s| {
s.spawn(|| {
println!("borrowed: {:?}", data);
});
});
// data is still usable here
println!("after scope: {:?}", data);
}move Olmadan Ödünç Alma
thread::scope içinde yerel değişkenleri move olmadan başvuru yoluyla okuyabilirsiniz. Birden çok kapsamlı iş parçacığı, normal başvurularda olduğu gibi aynı veriye ait değişmez ödünç almayı aynı anda paylaşabilir.
use std::thread;
fn main() {
let message = String::from("shared text");
thread::scope(|s| {
s.spawn(|| println!("thread 1 sees: {}", message));
s.spawn(|| println!("thread 2 sees: {}", message));
});
println!("main still owns: {}", message);
}Bir Dilim Üzerinde İşi Bölme
Yaygın bir desen, bir dilimi bölmek ve her iş parçacığının bir parçayı işlemesine izin vermektir. Kapsamlı iş parçacıkları bunu temiz bir şekilde yapmanızı sağlar; çünkü her iş parçacığı, klonlama gerektirmeden özgün dilimin bir bölümünü doğrudan ödünç alabilir.
use std::thread;
fn main() {
let numbers = [1, 2, 3, 4, 5, 6];
let (left, right) = numbers.split_at(3);
thread::scope(|s| {
s.spawn(|| {
let sum: i32 = left.iter().sum();
println!("left sum: {}", sum);
});
s.spawn(|| {
let sum: i32 = right.iter().sum();
println!("right sum: {}", sum);
});
});
}Dönüş Değerlerini Toplama
Normal iş parçacıkları gibi s.spawn da bir ScopedJoinHandle döndürür. İş parçacığının dönüş değerini almak için .join() çağrısını yapın. Tutamaçları toplayabilir ve sonuçları elde etmek için oluşturma işleminden sonra bunları birleştirebilirsiniz.
use std::thread;
fn main() {
let inputs = [2, 4, 6];
let mut handles = vec![];
thread::scope(|s| {
for &x in &inputs {
handles.push(s.spawn(move || x * x));
}
let results: Vec<i32> = handles.into_iter()
.map(|h| h.join().unwrap())
.collect();
println!("{:?}", results);
});
}Değiştirilebilir Ödünç Almalar Dikkat Gerektirir
İki kapsamlı iş parçacığı aynı verinin değiştirilebilir ödünç almalarını aynı anda tutamaz; bu, Rust'ın takma ad kurallarını ihlal eder. Birden çok iş parçacığından paylaşılan verileri değiştirmek için yine de bir Mutex gerekir, ancak tek bir iş parçacığı ayrık parçaların benzersiz değiştirilebilir ödünç almasını gerçekleştirebilir.
Aşağıda her iş parçacığı, split_at_mut aracılığıyla dizinin ayrı bir yarısını değiştirir.
use std::thread;
fn main() {
let mut data = [1, 2, 3, 4];
let (a, b) = data.split_at_mut(2);
thread::scope(|s| {
s.spawn(|| { for x in a.iter_mut() { *x *= 10; } });
s.spawn(|| { for x in b.iter_mut() { *x += 100; } });
});
println!("{:?}", data);
}Kapsam Otomatik Olarak Birleştirir
Her kapsamlı iş parçacığında join çağrısı yapmanız gerekmez. scope closure'ı döndüğünde Rust, devam etmeden önce henüz birleştirilmemiş tüm iş parçacıklarını otomatik olarak birleştirir. Ödünç almaların tüm iş parçacığı ömrü boyunca geçerli olmasının nedeni budur.
use std::thread;
use std::time::Duration;
fn main() {
let label = String::from("task");
thread::scope(|s| {
s.spawn(|| {
thread::sleep(Duration::from_millis(30));
println!("{} done", label);
});
println!("spawned, scope will wait");
});
println!("all scoped threads finished");
}Kapsamı Paylaşılan Değişiklikle Birleştirme
İş parçacıklarının aynı değeri değiştirmesi gerektiğinde kapsamlı iş parçacıklarını bir Mutex ile birleştirin. Kapsam, iş parçacıklarının yerel Mutex'i doğrudan ödünç almasına zaten izin verdiği için Arc kullanmanız gerekmez.
use std::sync::Mutex;
use std::thread;
fn main() {
let counter = Mutex::new(0);
thread::scope(|s| {
for _ in 0..5 {
s.spawn(|| {
let mut n = counter.lock().unwrap();
*n += 1;
});
}
});
println!("counter = {}", *counter.lock().unwrap());
}Kapsamlı ve Oluşturulmuş İş Parçacıkları: Hangisi Ne Zaman Kullanılmalı?
Çalışmanın kapsamı belliyse, bir işlev içinde tamamlanıyorsa ve Arc kullanmadan veya kopyalama yapmadan yığın verilerini ödünç almak istiyorsanız kapsamlı iş parçacıklarını kullanın.
Bir iş parçacığının geçerli işlevden daha uzun yaşaması veya programın tüm yaşam süresi boyunca çalışması gerekiyorsa thread::spawn kullanın. Kapsamlı iş parçacıkları kendi kapsamlarının dışına çıkamaz.
Paralel Map Örneği
Hepsini bir araya getirelim: bir vektörün her öğesini girdiyi ödünç alarak kendi iş parçacığında dönüştüren ve ardından sonuçları sıralı olarak toplayan küçük bir paralel map.
use std::thread;
fn parallel_double(items: &[i32]) -> Vec<i32> {
let mut handles = Vec::new();
let mut out = Vec::new();
thread::scope(|s| {
for &x in items {
handles.push(s.spawn(move || x * 2));
}
for h in handles {
out.push(h.join().unwrap());
}
});
out
}
fn main() {
let nums = vec![1, 2, 3, 4];
println!("{:?}", parallel_double(&nums));
}Hızlı Kontrol
Kapsamlı iş parçacıkları konusundaki anlayışınızı test edin.
Özet
Kapsamlı iş parçacıkları hakkında şunları öğrendiniz:
thread::spawn,'statickapanışlar gerektirir; kapsamlı iş parçacıkları gerektirmez.thread::scope, iş parçacıklarının yerel değişkenleri güvenli biçimde ödünç almasını sağlar.- Kapsam, dönmeden önce tüm iş parçacıklarını otomatik olarak birleştirir.
- Değiştirilebilir paylaşım için yine de bir
Mutexgerekir; ancak kapsam içindeArcgerekmez. - Sınırları belirli ve işlev yerelindeki paralellik için kapsamlı iş parçacıklarını kullanın.
Sıkça Sorulan Sorular
“Kapsamlı İş Parçacıkları” dersi ücretsiz mi?
Evet — “Kapsamlı İş Parçacıkları” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Learn Rust Coding kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Learn Rust Coding kursu toplamda 4 dersten oluşur.
“Kapsamlı İş Parçacıkları” dersinde ne öğreneceğim?
İş parçacıkları arasında ödünç alma Learn Rust Coding ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Learn Rust Coding öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Learn Rust Coding, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“Kapsamlı İş Parçacıkları” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Learn Rust Coding dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Learn Rust Coding dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- mpsc Kanalları
- Durumu Arc/Mutex ile Paylaşma
- Kapsamlı İş Parçacıkları
- Crossbeam Kanalları