在 C++11 中,线程同步和互斥可以使用互斥量、条件变量以及原子操作来实现。
互斥量主要用于控制对共享资源的访问。当多个线程需要访问同一共享资源时,需要采用互斥量来保证在任一时刻只有一个线程能访问该资源,从而防止数据竞争和内存泄漏的问题。C++11 引入了 std::mutex
,用于保护共享的数据或代码段。当一个线程需要访问共享资源时,它必须首先获取互斥量的锁,以确保其他线程无法同时访问该资源。当该线程完成它的工作后,必须释放互斥量的锁,以允许其他线程访问该共享资源。以下是一个简单的示例:
#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx;void print_thread_id(int id) {mtx.lock();std::cout << "Thread " << id << std::endl;mtx.unlock();
}int main() {std::thread t1(print_thread_id, 1);std::thread t2(print_thread_id, 2);t1.join();t2.join();return 0;
}
在上述代码中,mtx
变量被用作互斥量,print_thread_id()
函数需要获取 mtx
的锁才能执行输出任务。
条件变量主要用于线程之间的通信和同步。当一个线程需要等待某个事件的发生时(比如某个共享资源变为可用),可以调用条件变量的 wait()
函数将自己挂起等待,直到另外一个线程通知该条件变量,才能继续执行。以下是一个简单的示例:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>std::mutex mtx;
std::condition_variable cv;
bool ready = false;void print_id(int id) {std::unique_lock<std::mutex> lock(mtx);while(!ready)cv.wait(lock);std::cout << "Thread " << id << std::endl;
}void go() {std::unique_lock<std::mutex> lock(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(); // go!for (auto& th : threads) th.join();return 0;
}
在上述代码中,mtx
和 cv
变量被用作互斥量和条件变量,print_id()
函数需要获取 mtx
的锁才能执行输出任务,而 go()
函数则通过 cv.notify_all()
来通知等待条件变量的线程开始执行。
原子操作主要用于保证对特定数据类型的操作在多线程环境下是原子性的,即不会被中断。C++11 提供了 std::atomic
类型来实现原子操作,例如 std::atomic<int>
。以下是一个简单的示例:
#include <iostream>
#include <thread>
#include <atomic>std::atomic<int> counter(0);void increment_counter() {counter++;
}int main() {std::thread t1(increment_counter);std::thread t2(increment_counter);t1.join();t2.join();std::cout << "Counter value: " << counter << std::endl;return 0;
}
在上述代码中,counter
变量被定义为 std::atomic<int>
类型,而 increment_counter()
函数对其进行原子自增操作。