ใช้ข้อมูลร่วมกับ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- สร้างเธรด
- ย้ายข้อมูลเข้าเธรด
- ใช้ข้อมูลร่วมกับ Arc และ Mutex
- รอเธรดและรวบรวมผลลัพธ์