0Pricing
Learn Rust Coding · บทเรียน

ใช้ข้อมูลร่วมกับ Arc และ Mutex

เปลี่ยนสถานะที่ใช้ร่วมกันอย่างปลอดภัย

ใช้ข้อมูลร่วมกับ Arc และ Mutex เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน

ความจำเป็นของสถานะที่ใช้ร่วมกัน

บางครั้งหลายเธรดจำเป็นต้องอ่านหรืออัปเดตข้อมูลเดียวกัน การย้ายความเป็นเจ้าของไปให้เธรดเดียวจึงไม่เพียงพอ

Rust มอบความเป็นเจ้าของร่วมกันระหว่างเธรดอย่างปลอดภัยด้วย Arc และการแก้ไขข้อมูลอย่างปลอดภัยด้วย Mutex ทั้งสองอย่างนี้ทำให้เกิดสถานะที่ใช้ร่วมกันและแก้ไขได้

Arc: การนับจำนวนการอ้างอิงแบบอะตอมิก

Arc ย่อมาจากการนับจำนวนการอ้างอิงแบบอะตอมิก โดยทำงานคล้ายกับ Rc แต่ตัวนับใช้การดำเนินการแบบอะตอมิก จึงปลอดภัยเมื่อใช้ข้ามเธรด

การโคลน Arc ไม่ได้คัดลอกข้อมูล แต่เพียงเพิ่มจำนวนตัวนับและคืนตัวจัดการอีกตัวหนึ่งที่ชี้ไปยังค่าเดียวกัน

use std::sync::Arc;

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

การแชร์ Arc ระหว่างเธรด

หากต้องการแชร์ข้อมูลที่อ่านได้อย่างเดียว ให้โคลน Arc หนึ่งครั้งต่อเธรด แล้วนำโคลนแต่ละตัวเข้าไปในเธรด เธรดทั้งหมดจะชี้ไปยังพื้นที่จัดสรรเดียวกัน

เนื่องจาก Arc เป็นทั้ง Send และ Sync โค้ดนี้จึงคอมไพล์ได้อย่างราบรื่น

use std::sync::Arc;
use std::thread;

fn main() {
    let data = Arc::new(vec![10, 20, 30]);
    let mut handles = vec![];
    for i in 0..3 {
        let d = Arc::clone(&data);
        handles.push(thread::spawn(move || println!("{}", d[i])));
    }
    for h in handles { h.join().unwrap(); }
}

Arc เพียงอย่างเดียวอ่านได้เท่านั้น

Arc มอบความเป็นเจ้าของร่วมกัน แต่อนุญาตให้เข้าถึงค่าภายในได้เพียงแบบใช้ร่วมกันและแก้ไขไม่ได้

คุณไม่สามารถแก้ไขข้อมูลผ่าน Arc ได้โดยตรง เพราะการที่หลายเธรดถือมันพร้อมกันอาจทำให้เกิดการแย่งข้อมูล คุณต้องใช้ความสามารถในการแก้ไขข้อมูลภายในร่วมกับล็อก

Mutex: การกีดกันซึ่งกันและกัน

Mutex ทำหน้าที่ปกป้องข้อมูล เพื่อให้มีเธรดเพียงหนึ่งเธรดเข้าถึงข้อมูลได้ในแต่ละครั้ง คุณเรียก lock เพื่อขอสิทธิ์เข้าถึง

lock จะคืนค่าเป็น Result และการแกะค่าจะให้ตัวป้องกันแบบตัวชี้อัจฉริยะ เธรดอื่นจะถูกบล็อกจนกว่าตัวป้องกันจะถูกทำลาย

use std::sync::Mutex;

fn main() {
    let m = Mutex::new(0);
    {
        let mut guard = m.lock().unwrap();
        *guard += 5;
    }
    println!("{:?}", m);
}

ตัวป้องกันและ RAII

ค่าที่คืนโดย lock คือ MutexGuard คุณเข้าถึงข้อมูลภายในได้โดยยกเลิกการอ้างอิงด้วย *

เมื่อตัวป้องกันพ้นขอบเขตอายุการใช้งาน ล็อกจะถูกปล่อยโดยอัตโนมัติ รูปแบบ RAII นี้ช่วยป้องกันการลืมปลดล็อก

การใช้ Arc และ Mutex ร่วมกัน

หากต้องการแชร์สถานะที่แก้ไขได้ระหว่างเธรด ให้ห่อ Mutex ไว้ภายใน Arc โดย Arc แชร์ความเป็นเจ้าของ ส่วน Mutex ปกป้องการแก้ไข

รูปแบบ Arc<Mutex<T>> นี้เป็นวิธีมาตรฐานในการสร้างสถานะที่ใช้ร่วมกันและแก้ไขได้ใน Rust

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

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let c = Arc::clone(&counter);
    *c.lock().unwrap() += 1;
    println!("{}", *counter.lock().unwrap());
}

ตัวนับที่ใช้ร่วมกัน

ในตัวอย่างนี้มีเธรดสิบเธรดที่เพิ่มค่าตัวนับร่วมกันทีละหนึ่ง แต่ละเธรดจะโคลน Arc ล็อก Mutex แล้วบวกหนึ่ง

เนื่องจากล็อกทำให้การเข้าถึงเกิดขึ้นทีละลำดับ ยอดรวมสุดท้ายจึงเท่ากับสิบเสมอ

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

ทำส่วนวิกฤตให้สั้น

โค้ดที่ทำงานระหว่างถือครองล็อกเรียกว่าส่วนวิกฤต เธรดอื่นจะรออยู่ตรงนั้น ดังนั้นควรทำให้ส่วนนี้สั้น

ล็อก ทำการอัปเดตที่จำเป็นที่สุด แล้วปล่อยล็อก หลีกเลี่ยงการคำนวณหนักหรือการรับส่งข้อมูลขณะถือครองล็อก

use std::sync::Mutex;

fn main() {
    let m = Mutex::new(Vec::new());
    {
        let mut v = m.lock().unwrap();
        v.push(1);
    } // lock released here
    println!("{:?}", m.lock().unwrap());
}

การหยุดชะงักและการปนเปื้อน

หากเธรดหนึ่งล็อก Mutex เดิมสองครั้ง หรือเธรดสองเธรดล็อกมิวเทกซ์สองตัวในลำดับตรงข้ามกัน อาจเกิดการหยุดชะงักและค้างตลอดไป

หากเธรดเกิดพานิกขณะถือครองล็อก Mutex จะถูกทำเครื่องหมายว่าปนเปื้อน และการเรียก lock ในภายหลังจะคืนค่าเป็น Err

RwLock สำหรับผู้อ่านจำนวนมาก

เมื่อการอ่านมีจำนวนมากกว่าการเขียนอย่างมาก RwLock อาจเหมาะสมกว่า Mutex โดยอนุญาตให้มีผู้อ่านหลายรายพร้อมกัน หรือมีผู้เขียนเพียงรายเดียวแบบผูกขาด

ใช้ read สำหรับการเข้าถึงร่วมกัน และใช้ write สำหรับการเข้าถึงแบบผูกขาด

use std::sync::RwLock;

fn main() {
    let lock = RwLock::new(5);
    {
        let r = lock.read().unwrap();
        println!("read {}", *r);
    }
    *lock.write().unwrap() += 1;
    println!("{}", *lock.read().unwrap());
}

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจของคุณเกี่ยวกับ Arc และ Mutex

สรุป

คุณได้เรียนรู้ว่า Arc แชร์ความเป็นเจ้าของระหว่างเธรดด้วยการนับจำนวนการอ้างอิงแบบอะตอมิก แต่อนุญาตให้เข้าถึงได้เฉพาะแบบแก้ไขไม่ได้

Mutex ปกป้องการแก้ไขข้อมูล และส่งต่อตัวป้องกันที่ปล่อยล็อกเมื่อถูกทำลาย นำทั้งสองอย่างมารวมกันเป็น Arc<Mutex<T>> เพื่อสร้างสถานะที่ใช้ร่วมกันและแก้ไขได้ พร้อมระวังการหยุดชะงักและการปนเปื้อน

ต่อไปคุณจะได้ join เธรดและรวบรวมผลลัพธ์ของเธรด

คำถามที่พบบ่อย

บทเรียน “ใช้ข้อมูลร่วมกับ Arc และ Mutex” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ใช้ข้อมูลร่วมกับ Arc และ Mutex” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ใช้ข้อมูลร่วมกับ Arc และ Mutex”

เปลี่ยนสถานะที่ใช้ร่วมกันอย่างปลอดภัย คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “ใช้ข้อมูลร่วมกับ Arc และ Mutex” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม

ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. สร้างเธรด
  2. ย้ายข้อมูลเข้าเธรด
  3. ใช้ข้อมูลร่วมกับ Arc และ Mutex
  4. รอเธรดและรวบรวมผลลัพธ์
← กลับไปที่ Learn Rust Coding