Thread, mutex trong C++

Thread là một luồng thực thi (execution flow) độc lập bên trong cùng một tiến trình (process). Một chương trình có thể có nhiều thread chạy song song hoặc gần như song song trên nhiều CPU core.

Thread giúp chương trình nhanh hơn khi các công việc độc lập; nhưng càng nhiều thread thì việc đồng bộ càng phức tạp và dễ phát sinh lỗi (tốn RAM, Context switch, Scheduler overhead)

Khi nào nên dùng thread?

  • Công việc độc lập có thể chạy song song vd: xử lý 10.000 ảnh, thay vì xử lí tuần tự ảnh 1 –> ảnh 2 –> ảnh 3, chúng ta có thể tạo thread 1 xử lý anh 1-2500, thread 2 xử lý ảnh 2501-5000,…
  • Tránh làm treo giao diện UI Thread –> tạo Worker Thread chạy tác vụ nặng (vd: load file 2GB)
  • Server xử lý nhiều client A, B, C… tạo std::thread(clientHandler, socketA); std::thread(clientHandler, socketB);
  • Các tác vụ nền vd: download file, ghi log, đồng bộ dữ liệu, backup,…

Khi nào KHÔNG nên dùng thread?

  • Dữ liệu phụ thuộc lẫn nhau A phải xong mới chạy B, B phải xong mới chạy C

Ví dụ tạo thread

main() chạy trên thread chính (main thread).

std::thread t(printMessage); tạo thread mới thực thi hàm printMessage()

join() bắt thread chính đợi thread con kết thúc.

Nếu không gọi join() hoặc detach(), chương trình sẽ lỗi khi đối tượng thread bị hủy.

Compile với -pthread là tùy chọn cần thiết để hỗ trợ đa luồng trên Linux/GCC.

Thứ tự không cố định vì các thread chạy song song.

Thread 2 dang chay
Thread 1 dang chay
Thread 3 dang chay
btest.cpp
// Ví dụ chạy 1 thread
#include <iostream>
#include <thread>

void printMessage()
{
    for (int i = 1; i <= 5; i++)
    {
        std::cout << "thread dang chay " << i << std::endl;
    }
}

int main()
{
    std::cout << "main thread bat dau" << std::endl;
	
    // Tạo thread mới
    std::thread t(printMessage);

    // Chờ thread kết thúc
    t.join();

    std::cout << "main thread ket thuc" << std::endl;

    return 0;
}
[btnguyen@hpserver btest]$ g++ btest.cpp -o btest -pthread
[btnguyen@hpserver btest]$ ./btest
main thread bat dau
thread dang chay 1
thread dang chay 2
thread dang chay 3
thread dang chay 4
thread dang chay 5
main thread ket thuc
[btnguyen@hpserver btest]$
btest.cpp
// Ví dụ chạy nhiều threads
#include <iostream>
#include <thread>

void printMessage(int id)
{
    std::cout << "Thread " << id << " dang chay" << std::endl;
}

int main()
{
    std::cout << "main thread bat dau" << std::endl;
	
    // Tạo threads mới
    std::thread t1(printMessage, 1);
    std::thread t2(printMessage, 2);
    std::thread t3(printMessage, 3);

    // Chờ threads kết thúc
    t1.join();
    t2.join();
    t3.join();

    std::cout << "main thread ket thuc" << std::endl;

    return 0;
}
[btnguyen@hpserver btest]$ g++ btest.cpp -o btest -pthread
[btnguyen@hpserver btest]$ ./btest
main thread bat dau
Thread 2 dang chay
Thread 1 dang chay
Thread 3 dang chay
main thread ket thuc
[btnguyen@hpserver btest]$

Chia sẻ dữ liệu với mutex

mutex giúp tránh race condition khi nhiều thread cùng cập nhật biến counter. Nếu không có mutex, có thể nhận 173124, 198622,... do tranh chấp dữ liệu thay vì kết quả mong muốn 200000

btest.cpp
#include <iostream>
#include <thread>
#include <mutex>

int counter = 0;
std::mutex mtx;

void increment()
{
    for (int i = 0; i < 100000; i++)
    {
        std::lock_guard<std::mutex> lock(mtx);
        counter++;
    }
}

int main()
{
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    std::cout << "Counter = " << counter << std::endl;

    return 0;
}
[btnguyen@hpserver btest]$ g++ btest.cpp -o btest -pthread
[btnguyen@hpserver btest]$ ./btest
Counter = 200000
[btnguyen@hpserver btest]$

So sánh pthread, boost::thread, std::thread

Tiêu chípthreadboost::threadstd::thread
Ra đờiPOSIXBoostC++11
Chuẩn hóaPOSIXThư viện bên ngoàiChuẩn C++
Ngôn ngữCC++C++
Đa nền tảngChủ yếu Unix/LinuxCóCó
Cần cài thêmKhôngCó BoostKhông
Type-safeKhôngCóCó
Hiện nayLegacy/SystemÍt dùng hơnKhuyến nghị

Leave a Comment