解锁C++多线程:同步机制与互斥锁详解

线程同步与互斥

在多线程编程中,线程同步互斥是确保程序正确执行和避免数据竞争的重要概念。

  • 线程同步:指的是多个线程按照某种特定的顺序来执行,或者说它们之间的某些操作是协调一致的。同步的目的是控制线程之间的执行顺序,以确保它们能够正确地交互和共享数据。

  • 互斥(Mutex,即Mutual Exclusion):指的是在同一时刻,只允许一个线程访问某个资源(如内存中的某个变量)。互斥的目的是保护共享资源,防止多个线程同时修改数据导致的竞态条件(Race Condition)和数据不一致。

在C++中实现线程同步与互斥

C++11及以后的版本提供了丰富的线程库,包括等头文件,用于支持多线程编程。

互斥锁(Mutex)

互斥锁是最基本的同步机制之一,用于保护共享资源。

#include   
#include   
#include   
  
std::mutex mtx; // 定义一个互斥锁  
int count = 0; // 一个被保护的共享资源  
  
void safe_increment() {  
    mtx.lock(); // 上锁  
    ++count;  
    std::cout << "Count is now " << count << std::endl;  
    mtx.unlock(); // 解锁  
}  
  
int main() {  
    std::thread t1(safe_increment);  
    std::thread t2(safe_increment);  
  
    t1.join();  
    t2.join();  
  
    return 0;  
}
锁保护(std::lock_guard)

为了避免忘记释放锁,可以使用std::lock_guardstd::unique_lock。这些类会在其析构时自动释放锁。

#include   
#include   
#include   
  
std::mutex mtx;  
int count = 0;  
  
void safe_increment() {  
    std::lock_guard lock(mtx); // 上锁,并在作用域结束时自动解锁  
    ++count;  
    std::cout << "Count is now " << count << std::endl;  
}  
  
int main() {  
    std::thread t1(safe_increment);  
    std::thread t2(safe_increment);  
  
    t1.join();  
    t2.join();  
  
    return 0;  
}
条件变量(std::condition_variable)

条件变量用于线程之间的同步,允许一个或多个线程在某个条件成立之前等待。

#include   
#include   
#include   
#include   
  
std::mutex mtx;  
std::condition_variable cv;  
bool ready = false;  
  
void print_id(int id) {  
    std::unique_lock lck(mtx);  
    while (!ready) cv.wait(lck); // 等待条件变量  
    std::cout << "Thread " << id << '\n';  
}  
  
void go() {  
    std::unique_lock lck(mtx);  
    ready = true;  
    cv.notify_all(); // 通知所有等待的线程  
}  
  
int main() {  
    std::thread threads[10];  
    for (int i = 0; i < 10; ++i)  
        threads[i] = std::thread(print_id, i);  
  
    std::cout << "10 threads ready to race...\n";  
    go(); // 允许所有线程继续执行  
  
    for (auto& th : threads) th.join();  
  
    return 0;  
}
#include   
#include   
#include   
#include   
  
std::mutex mtx;  
std::condition_variable cv;  
bool ready = false;  
  
void print_id(int id) {  
    std::unique_lock lck(mtx);  
    while (!ready) cv.wait(lck); // 等待条件变量  
    std::cout << "Thread " << id << '\n';  
}  
  
void go() {  
    std::unique_lock lck(mtx);  
    ready = true;  
    cv.notify_all(); // 通知所有等待的线程  
}  
  
int main() {  
    std::thread threads[10];  
    for (int i = 0; i < 10; ++i)  
        threads[i] = std::thread(print_id, i);  
  
    std::cout << "10 threads ready to race...\n";  
    go(); // 允许所有线程继续执行  
  
    for (auto& th : threads) th.join();  
  
    return 0;  
}

在这个例子中,print_id函数中的线程在ready变量为true之前会一直等待。go函数通过改变ready的值并调用cv.notify_all()来唤醒所有等待的线程。

你可能感兴趣的:(c++)