0Pricing
Learn Rust Coding · Pelajaran

Berbagi State dengan Arc/Mutex

Data bersama yang aman

Berbagi State dengan Arc/Mutex adalah pelajaran Learn Rust Coding gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Learn Rust Coding, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Learn Rust Coding mencakup 4 pelajaran total.

Mengapa Keadaan Bersama Sulit

Terkadang pengiriman pesan tidak cukup dan beberapa utas benar-benar perlu membaca serta menulis data yang sama. Rust tidak akan mengizinkan Anda berbagi nilai yang dapat diubah di antara utas tanpa perlindungan, karena hal itu dapat menyebabkan perlombaan data.

Dua alat yang Anda gabungkan adalah:

  • Arc untuk kepemilikan bersama di antara utas.
  • Mutex untuk perubahan eksklusif yang aman.

Rc Tidak Aman untuk Utas

Rc menyediakan kepemilikan bersama, tetapi hanya pada satu utas. Jumlah referensinya tidak disinkronkan, sehingga kompiler menolak pengirimannya di antara utas. Untuk berbagi di banyak utas, Anda memerlukan Arc (Penghitung Referensi Atomik).

Arc berperilaku seperti Rc, tetapi memperbarui jumlahnya dengan operasi atomik, sehingga penggandaannya aman di antara utas.

use std::sync::Arc;

fn main() {
    let data = Arc::new(vec![1, 2, 3]);
    let clone1 = Arc::clone(&data);
    println!("original: {:?}", data);
    println!("clone:    {:?}", clone1);
    println!("count:    {}", Arc::strong_count(&data));
}

Mutex Menyediakan Akses Eksklusif

Mutex membungkus data dan menjamin bahwa hanya satu utas yang mengaksesnya pada satu waktu. Anda memanggil .lock() untuk mendapatkan MutexGuard, yang melakukan dereferensi ke nilai di dalamnya. Kunci dilepaskan secara otomatis ketika penjaga keluar dari cakupan.

use std::sync::Mutex;

fn main() {
    let m = Mutex::new(5);
    {
        let mut num = m.lock().unwrap();
        *num += 10;
    } // guard dropped here, lock released
    println!("value = {:?}", m.lock().unwrap());
}

Menggabungkan Arc dan Mutex

Untuk berbagi data yang dapat diubah di antara utas, bungkus data tersebut sebagai Arc>:

  • Arc memungkinkan banyak utas memiliki pegangan ke data yang sama.
  • Mutex memungkinkan setiap utas mengubahnya dengan aman, satu per satu.

Gandakan Arc untuk setiap utas sebelum menjalankannya.

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let c = Arc::clone(&counter);
    let handle = thread::spawn(move || {
        let mut n = c.lock().unwrap();
        *n += 1;
    });
    handle.join().unwrap();
    println!("counter = {}", *counter.lock().unwrap());
}

Penghitung Bersama di Banyak Utas

Contoh klasiknya: sepuluh utas masing-masing menambah penghitung bersama. Setiap utas memegang pengganda Arc-nya sendiri dan mengunci Mutex untuk menambahkan satu. Setelah semua utas digabungkan, totalnya tepat 10, tanpa perlombaan data.

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 || {
            let mut num = c.lock().unwrap();
            *num += 1;
        }));
    }
    for h in handles {
        h.join().unwrap();
    }
    println!("Result: {}", *counter.lock().unwrap());
}

Cakupan Kunci Itu Penting

MutexGuard menahan kunci hingga dilepaskan. Menahannya selama pekerjaan yang lambat akan menghambat utas lain. Buat bagian kritis tetap singkat: kunci, ubah, lepaskan. Membungkus kunci dalam blok kecil memastikan kunci dilepaskan sebelum pemrosesan tambahan apa pun.

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let log = Arc::new(Mutex::new(Vec::new()));
    let mut handles = vec![];
    for i in 0..3 {
        let l = Arc::clone(&log);
        handles.push(thread::spawn(move || {
            {
                let mut v = l.lock().unwrap();
                v.push(i);
            } // released quickly
        }));
    }
    for h in handles { h.join().unwrap(); }
    let mut result = log.lock().unwrap().clone();
    result.sort();
    println!("{:?}", result);
}

Kebuntuan: Risiko Nyata

Kebuntuan terjadi ketika dua utas masing-masing memegang kunci yang dibutuhkan oleh utas lainnya, lalu keduanya menunggu selamanya. Rust mencegah perlombaan data, tetapi tidak mencegah kebuntuan. Hindari kebuntuan dengan selalu mengunci beberapa mutex dalam urutan yang sama dan menjaga kunci tetap singkat.

Hindari juga mengunci Mutex yang sama dua kali pada satu utas; Mutex standar tidak dapat dikunci ulang.

Poisoning Saat Utas Panik

Jika sebuah utas panik saat memegang kunci, Mutex menjadi tercemar. Pemanggilan .lock() berikutnya mengembalikan Err, sehingga Anda mengetahui bahwa data mungkin tidak konsisten. Anda dapat memulihkan penjaga di dalamnya melalui into_inner() pada galat tersebut jika Anda memutuskan bahwa data masih dapat digunakan.

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let data = Arc::new(Mutex::new(0));
    let d = Arc::clone(&data);
    let _ = thread::spawn(move || {
        let mut g = d.lock().unwrap();
        *g = 7;
        panic!("boom"); // poisons the mutex
    }).join();
    match data.lock() {
        Ok(g) => println!("ok: {}", *g),
        Err(poisoned) => println!("recovered: {}", *poisoned.into_inner()),
    }
}

RwLock untuk Banyak Pembaca

Ketika pembacaan jauh lebih sering daripada penulisan, RwLock dapat lebih cepat daripada Mutex. Alat ini mengizinkan banyak pembaca secara bersamaan atau satu penulis. Gunakan .read() untuk akses bersama dan .write() untuk akses eksklusif.

use std::sync::{Arc, RwLock};
use std::thread;

fn main() {
    let config = Arc::new(RwLock::new(String::from("v1")));
    let reader = Arc::clone(&config);
    let r = thread::spawn(move || {
        let val = reader.read().unwrap();
        println!("read: {}", *val);
    });
    r.join().unwrap();
    {
        let mut w = config.write().unwrap();
        *w = String::from("v2");
    }
    println!("final: {}", *config.read().unwrap());
}

Atomik untuk Penghitung Sederhana

Untuk satu penghitung bilangan bulat, Mutex lengkap berlebihan. Tipe seperti AtomicUsize menyediakan pembaruan tanpa kunci melalui metode seperti fetch_add. Bungkus tipe tersebut dalam Arc untuk membagikannya di antara utas. Pilih sebuah Ordering; SeqCst adalah bawaan aman yang paling sederhana.

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;

fn main() {
    let counter = Arc::new(AtomicUsize::new(0));
    let mut handles = vec![];
    for _ in 0..5 {
        let c = Arc::clone(&counter);
        handles.push(thread::spawn(move || {
            c.fetch_add(1, Ordering::SeqCst);
        }));
    }
    for h in handles { h.join().unwrap(); }
    println!("count = {}", counter.load(Ordering::SeqCst));
}

Memilih Alat yang Tepat

Panduan singkat untuk keadaan bersama:

  • Channel: memindahkan kepemilikan dengan gaya alur pemrosesan.
  • Arc<Mutex>: struktur bersama yang dapat diubah, dengan campuran pembacaan/penulisan.
  • Arc<RwLock>: data bersama yang didominasi pembacaan.
  • Atomics: penghitung atau penanda primitif tunggal.

Utamakan alat paling sederhana yang sesuai; gunakan kunci hanya ketika pengiriman pesan tidak memodelkan masalah dengan baik.

Pemeriksaan Singkat

Uji pemahaman Anda tentang keadaan bersama.

Rangkuman

Anda telah mempelajari cara berbagi keadaan dengan aman di antara utas:

  • Arc memungkinkan kepemilikan bersama yang aman untuk utas; Rc tidak.
  • Mutex memberikan perubahan eksklusif melalui penjaga yang membuka kunci secara otomatis.
  • Arc<Mutex<T>> adalah pola standar untuk data bersama yang dapat diubah.
  • Jaga cakupan kunci tetap singkat; waspadai kebuntuan dan pencemaran.
  • RwLock cocok untuk data yang didominasi pembacaan; atomik cocok untuk penghitung sederhana.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Berbagi State dengan Arc/Mutex” gratis?

Ya — teks lengkap “Berbagi State dengan Arc/Mutex” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Learn Rust Coding, upgrade ke CoddyKit PRO. Kursus Learn Rust Coding mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Berbagi State dengan Arc/Mutex”?

Data bersama yang aman Kamu berlatih Learn Rust Coding dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Learn Rust Coding?

Tidak diperlukan pengalaman sebelumnya. Learn Rust Coding di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Berbagi State dengan Arc/Mutex” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Learn Rust Coding ini?

Ya. Setiap pelajaran Learn Rust Coding menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Kanal mpsc
  2. Berbagi State dengan Arc/Mutex
  3. Thread Berscope
  4. Kanal Crossbeam
← Kembali ke Learn Rust Coding