二者都是 C++ 标准库中用于管理互斥锁(mutex)的 RAII(Resource Acquisition Is Initialization)机制的类。这些类可以确保互斥锁在构造时被获取,在析构时被释放,从而避免死锁和资源泄漏问题。不过,它们在功能和使用方式上有一些重要区别。
std::lock_guard
td::lock_guard
是一个简单的、轻量级的锁管理器,它在构造时获取锁,在析构时释放锁。其主要特点是不能显式地解锁或重新锁定。
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>std::mutex mtx;void threadFunction(int threadID) {try {std::lock_guard<std::mutex> lock(mtx);// mtx 在此范围内锁定std::cout << "Thread " << threadID << " is running..." << std::endl;// 模拟一些工作std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::cout << "Thread " << threadID << " has finished working." << std::endl;// mtx 在此范围末尾解锁} catch (const std::exception& e) {std::cerr << "Exception caught in thread " << threadID << ": " << e.what() << std::endl;}
}int main() {const int numThreads = 5;std::vector<std::thread> threads;for (int i = 0; i < numThreads; ++i) {threads.emplace_back(threadFunction, i);}for (auto& t : threads) {t.join();}std::cout << "All threads have completed." << std::endl;return 0;
}
每个线程在输出信息时获取了互斥锁,确保了标准输出的操作是原子的,避免了竞争条件导致的输出混乱。
std::unique_lock
std::unique_lock
是一个灵活但稍复杂的锁管理器。它允许更多的锁操作,如延迟锁定、解锁和重新锁定。
// unique_lock example
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lockstd::mutex mtx; // mutex for critical sectionvoid print_block (int n, char c) {// critical section (exclusive access to std::cout signaled by lifetime of lck):std::unique_lock<std::mutex> lck (mtx);for (int i=0; i<n; ++i) { std::cout << c; }std::cout << '\n';
}int main ()
{std::thread th1 (print_block,50,'*');std::thread th2 (print_block,50,'$');th1.join();th2.join();return 0;
}
order of lines may vary, but characters are never mixed.
void threadFunction() {std::unique_lock<std::mutex> lock(mtx);// 可以显式解锁std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟工作std::cout << "Thread is running..." << std::endl;lock.unlock();// 可以重新加锁lock.lock();std::cout << "Thread is finishing..." << std::endl;
}int main() {std::thread t1(threadFunction);std::thread t2(threadFunction);t1.join();t2.join();return 0;
}