ข้ามไปยังเนื้อหา

Concurrency, Testing & Cargo

หนึ่งในข้อเรียกร้องที่กล้าหาญที่สุดของ Rust คือ fearless concurrency (การทำงานพร้อมกันอย่างไม่หวั่นเกรง): การเขียนโปรแกรมแบบหลาย-thread โดยไม่มี data race ที่รบกวน C, C++ หรือแม้แต่ Java คอมไพเลอร์บังคับใช้กฎ ownership เดิมที่ขอบเขตของ thread เปลี่ยนบั๊กทั้งคลาสให้เป็น compile-time error แทนที่จะเป็น runtime failure ที่หาได้ยาก

โมดูลนี้สำรวจสี่เสาหลักของ Rust ในการใช้งานจริง:

บทเรียนหัวข้อรันได้
Threadsstd::thread, Arc<Mutex<T>>, การ join handleได้ — Playground ใน browser
Channelsstd::sync::mpsc, send/receive, การส่งต่อ ownershipได้ — Playground ใน browser
Async Introasync/.await, futures, tokio runtimeเฉพาะ Cargo project เท่านั้น
Cargo & Testscargo new, #[test], cargo testเฉพาะ Cargo project เท่านั้น

standard library ของ Rust มี OS threads ผ่าน std::thread แต่ละ thread คือ thread ระดับ OS จริง ๆ ที่มี stack ของตัวเอง สถานะที่แชร์กันระหว่าง thread ถูกป้องกันด้วย Arc<Mutex<T>> — คอมไพเลอร์จะไม่ยอมให้คุณส่งประเภทที่ไม่ใช่ Send ข้ามขอบเขต thread

สำหรับ workload ที่ผูกติดกับ I/O — network server, การดำเนินการกับไฟล์, งานที่เกิดขึ้นพร้อมกันจำนวนมาก — โมเดล async/.await มีประสิทธิภาพมากกว่า โดยใช้ event loop แบบ single-threaded หรือ multi-threaded (โดยทั่วไปคือ tokio) เพื่อกำหนดเวลาของงานนับพัน ๆ งานโดยไม่มีค่าใช้จ่ายของ OS thread ต่องาน

ในภาษาส่วนใหญ่ data race คือปัญหา runtime คุณเขียนโค้ด รันขึ้นมา และบางครั้งโปรแกรมก็ crash หรือส่งคืนผลลัพธ์ที่ผิดเมื่อมีการโหลดสูง ใน Rust:

  • ประเภทที่เป็น Send หมายความว่าปลอดภัยที่จะย้ายไปยัง thread อื่น
  • ประเภทที่เป็น Sync หมายความว่าปลอดภัยที่จะแชร์ reference ข้าม thread
  • คอมไพเลอร์ปฏิเสธโค้ดที่ละเมิดสัญญาเหล่านี้ — ไม่ต้องการ sanitizer หรือ runtime check

นี่คือโปรแกรม Rust แบบ concurrent ที่เล็กที่สุดที่มีความหมาย — spawn thread รอ แล้วทำงานต่อใน main

use std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("Hello from a spawned thread!");
});
handle.join().unwrap();
println!("Main thread done.");
}
การที่ประเภทหนึ่งเป็น Send ใน Rust หมายความว่าอะไร?
ประเภทใดใน standard library ที่ใช้แชร์ mutable state ระหว่าง thread อย่างปลอดภัย?
ควรใช้ async/await แทน OS thread เมื่อใด?