· Phạm Thành Nam · Ngôn ngữ Rust · 4 phút đọc

30 Ngày học Rust - Day 18: Chinh phục Da luồng (Concurrency) - Cú đâm quyết định của Rust

Day 18: Concurrency ở C/C++ là một thảm họa lỗi ngầm. Khám phá cách Rust sử dụng Channels, Metux và Arc để hô biến Multi-threading trở thành 'Trải nghiệm không sợ hãi'.

Day 18: Concurrency ở C/C++ là một thảm họa lỗi ngầm. Khám phá cách Rust sử dụng Channels, Metux và Arc để hô biến Multi-threading trở thành 'Trải nghiệm không sợ hãi'.

Nỗi khiếp sợ mang tên Đa luồng

Viết code tuần tự từ trên xuống dưới trên môi trường Đơn luồng (Single Thread) rất dễ. JS, PHP, Python đều sống thọ hàng chục năm qua cái vòng lặp Đơn luồng đó.

Nhưng nếu khách hàng có Mạng Lưới Server 64 Cores CPU. Và Web API của bạn đang chỉ chạy trên 1 Core! Bạn quăng vô sọt rác 98% sức mạnh chiếc máy đó do không biết viết Đa luồng song song (Multi-threading).

Viết đa luồng bằng C++ là đánh cuộc với Quỷ Tuyến rò (Data Races). Hai cái Thread Cùng Chỉnh sửa biến SoTien. Thread 1 đang báo Trừ, Thread 2 lao bào báo Cộng. Thế là Số Tiền Mất Đồng Bộ, Vỡ Nát Giá Trị Không Cứu Kì Nổi. Đó là nơi Rust tung chiêu “Fearless Concurrency” (Đa luồng không sợ hãi). Nhờ Ownership, Trình Biên Dịch tóm cổ 100% Data Races từ lúc Code.

Sơ đồ mô phỏng các luồng chạy ngầm độc lập qua Channel

1. Ném Code vào Thread và Lệnh cướp bóc move

Tạo một rãnh Tách Core chạy Song Song:

use std::thread;
use std::time::Duration;

fn main() {
    let mut data = vec![1, 2, 3];

    // Thread:spawn đẻ ra 1 Luồng Core mới, bưng Data chạy tự do
    let handle = thread::spawn(move || {
        println!("Mảng nằm trong Thread Con: {:?}", data);
    });

    handle.join().unwrap(); // Lệnh Dẫn Nước: Chờ Thằng Thread Con Đóng Cửa Mới Tắt App
}

Tại sao phải có move? Trình compile cực kì thông minh: Ê DEV, Mày ném mảng Data Vô Thread con. Nhỡ m làm rớt đóng mất Hàm Cái trước khi Thằng Con Kịp Chạy Thì Chết à? Bắt buộc Xài chữ move để QUĂNG QUYỀN SỞ HỮU MẢNG sang hẳn thằng Con. Code Rust ÉP BẠN ĐI ĐÚNG YẾT HẦU.

2. Truyền Tiên nhắn Gửi Nhau Qua Channels (Ống giao tiếp)

Nếu Thread 1 Vừa Chạy vọc mạng, muốn ném Báo Cáo Sang Thread 2 đang tính điểm Đỗ Cổng? Đừng dùng Cụm Biến Shared Mảng, dùng Channels (mô hình thông điệp - Message Passing của ngôn ngữ Erlang/Go).

use std::sync::mpsc;
use std::thread;

fn main() {
    // tx = Máy phát tín, rx = Cục Rì Civer Đón Hộp
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let hop_nho = String::from("Hàng ship Viettel");
        tx.send(hop_nho).unwrap();
        // println!("{}", hop_nho); <- LỖI CHẾT MOE! Cậu vừa gỡ Ownership ship qua ống gửi, Cậu lấy lại In lỗi Liền! 
    });

    let thu_nhan = rx.recv().unwrap();
    println!("App Tổng Đã Nhận: {}", thu_nhan);
}

3. Khóa Vuốt Mutex và Vòng Tay Arc

Nếu Cực Bí và 5 Thread BUỘC PHẢI Cộng Trừ Trực tiếp và Chung Cái Cục Biến Băng Chuyền?

  • Mutex: Cái Ổ Chìa Khóa Cắt Điện. (Muốn sờ Data, Mày cắm Key khóa lại. Vọc xong rớt Key ra cho Thằng Kế nhào vô. Đảm Bảo Tuần tự).
  • Arc (Atomic Reference Counted): Một phiên bản Siêu Vững của Ngày 17 (Rc). Phóng bóng clone Data Xả Ra Các Core Thread Tranh Gành Lõi Rễ.
use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let diem_so = Arc::new(Mutex::new(0)); // Dính Kép Vũ Khí Max
    let mut ds_cung = vec![];

    for _ in 0..10 {
        let diem_clone = Arc::clone(&diem_so);
        let qua_chuy = thread::spawn(move || {
            let mut con_tro = diem_clone.lock().unwrap(); // Khoá Giật Lõi Lên
            *con_tro += 1;
        });
        ds_cung.push(qua_chuy);
    }

    for c in ds_cung { c.join().unwrap(); }
    println!("Tổng Nút Click Max: {}", *diem_so.lock().unwrap()); // Chắc chắn 10. Không Bao Giờ Trật Data!
}

Sẵn sàng cho Ngày 19? Đập Thủng Nóc Nỗi Lo Chạy Hàng Triệu Dòng Chảy. Ta Quay Trở Lại Với Mặt Đất Kiến Trúc Mã Vạch Kỹ Năng Thiết Kế Hệ Thống Kế Thừa. Rốt Cục Rust Bắt Chước Java OOP Ra Sướng Mặt Nào? Nạp Đạn Tới: [Day 19: Thiết Kế Object-Oriented trong Lốt Con Ngại].

Chuỗi bài viết

30 Ngày Trở Thành Rustacean Tinh Hoa

Phần 18 / 30

30 bài viết
  1. Phần 1 30 Ngày học Rust - Day 1: Lời chào thế giới và Vũ khí Cargo
  2. Phần 2 30 Ngày học Rust - Day 2: Biến, Bất biến (Mutability) và Shadowing
  3. Phần 3 30 Ngày học Rust - Day 3: Luồng điều khiển (Control Flow) và sức mạnh của Match
  4. Phần 4 30 Ngày học Rust - Day 4: Ownership - Khái niệm định hình cỗ thần khí Rust
  5. Phần 5 30 Ngày học Rust - Day 5: Khóa học nhặt đồ chung với References & Borrowing
  6. Phần 6 30 Ngày học Rust - Day 6: Đắp nặn dự án với Structs và Methods
  7. Phần 7 30 Ngày học Rust - Day 7: Quyền năng vô song của Enums và Pattern Matching
  8. Phần 8 30 Ngày học Rust - Day 8: Quản lý dự án với Packages, Crates và Modules
  9. Phần 9 30 Ngày học Rust - Day 9: Các bộ sưu tập chung (Vectors, Strings, Hash Maps)
  10. Phần 10 30 Ngày học Rust - Day 10: Trị dứt điểm Ác mộng Lỗi (Error Handling)
  11. Phần 11 30 Ngày học Rust - Day 11: Generics - Ma thuật Đa hình kiểu dữ liệu
  12. Phần 12 30 Ngày học Rust - Day 12: Traits - Kẻ ban phát quyền năng và Lập pháp Hành vi
  13. Phần 13 30 Ngày học Rust - Day 13: Vượt qua Boss cuối 'Lifetimes' - Sinh Mệnh Biến
  14. Phần 14 30 Ngày học Rust - Day 14: Tận diệt Bug từ trứng nước bằng Automated Tests
  15. Phần 15 30 Ngày học Rust - Day 15: Thực chiến Build Command Line App (CLI) đầu đời
  16. Phần 16 30 Ngày học Rust - Day 16: Functional Magic chốn trần gian (Closures & Iterators)
  17. Phần 17 30 Ngày học Rust - Day 17: Quyền năng của Smart Pointers
  18. Phần 18 30 Ngày học Rust - Day 18: Chinh phục Da luồng (Concurrency) - Cú đâm quyết định của Rust
  19. Phần 19 30 Ngày học Rust - Day 19: Tranh cãi Lập trình hướng đối tượng (OOP) trong Rust
  20. Phần 20 30 Ngày học Rust - Day 20: Mổ xẻ nghệ thuật Advanced Pattern Matching
  21. Phần 21 30 Ngày học Rust - Day 21: Sức mạnh tối thượng của Advanced Traits
  22. Phần 22 30 Ngày học Rust - Day 22: Về Phe Bóng Tối với Unsafe Rust
  23. Phần 23 30 Ngày học Rust - Day 23: Quyền năng của Đấng Tạo Hóa (Declarative Macros)
  24. Phần 24 30 Ngày học Rust - Day 24: Siêu Năng Lực Procedural Macros (Macro Thủ Tục)
  25. Phần 25 30 Ngày học Rust - Day 25: Xây dựng TCP Web Server Đa Luồng (Phần 1: Lõi Socket)
  26. Phần 26 30 Ngày học Rust - Day 26: Xây dựng TCP Web Server Đa Luồng (Phần 2: Bắn trả File HTML)
  27. Phần 27 30 Ngày học Rust - Day 27: Xây dựng TCP Web Server Đa Luồng (Phần 3: The Thread Pool)
  28. Phần 28 30 Ngày học Rust - Day 28: Xây dựng TCP Web Server Đa Luồng (Phần 4: Graceful Shutdown)
  29. Phần 29 30 Ngày học Rust - Day 29: Lên đỉnh Web Server Thực Chiến với Axum và Tokio
  30. Phần 30 30 Ngày học Rust - Day 30: Vượt Vọng Vàng - Đúc Kết Hành Trình Rustacean Tinh Hoa

Bình luận

Quay lại Blog

Bài viết liên quan

Xem tất cả bài viết »