在C++中,多线程编程通常涉及到并发访问共享资源的问题。为了避免并发访问导致的数据不一致或竞争条件,我们需要对共享资源进行加锁和解锁操作。C++11标准引入了多线程支持,包括锁的概念,主要通过库中提供的各种互斥锁(mutex)来实现。
- std::mutex的使用
std::mutex是最基本的互斥锁,用来保护共享数据,防止多个线程同时访问同一资源。
加锁:使用lock()方法可以加锁。
解锁:使用unlock()方法可以解锁。
cpp
Copy code
#include
#include
#include
std::mutex mtx; // 全局互斥锁
void print_block(int n, char c) {
mtx.lock();
for (int i = 0; i < n; ++i) { std::cout << c; }
std::cout << ‘\n’;
mtx.unlock();
}
int main() {
std::thread th1(print_block, 50, ‘*’);
std::thread th2(print_block, 50, ‘$’);
th1.join();
th2.join();
return 0;
}
2. std::lock_guard的使用
为了避免因异常等原因导致忘记解锁,C++提供了std::lock_guard对象,它是一个作用域锁,当作用域结束时自动释放锁。
cpp
Copy code
#include
#include
#include
std::mutex mtx; // 全局互斥锁
void print_block(int n, char c) {
std::lock_guardstd::mutex guard(mtx);
for (int i = 0; i < n; ++i) { std::cout << c; }
std::cout << ‘\n’;
// 当guard对象离开作用域时,自动调用其析构函数,解锁mtx
}
int main() {
std::thread th1(print_block, 50, ‘*’);
std::thread th2(print_block, 50, ‘$’);
th1.join();
th2.join();
return 0;
}
3. std::unique_lock的使用
std::unique_lock是一个比std::lock_guard更灵活的锁管理器,它允许我们延迟锁定、手动锁定和解锁,以及将锁的所有权从一个unique_lock转移到另一个。
cpp
Copy code
#include
#include
#include
std::mutex mtx; // 全局互斥锁
void print_block(int n, char c) {
std::unique_lockstd::mutex ulock(mtx, std::defer_lock); // 延迟锁定
// 做一些其他工作…
ulock.lock(); // 现在手动加锁
for (int i = 0; i < n; ++i) { std::cout << c; }
std::cout << ‘\n’;
// ulock对象离开作用域时自动释放锁
}
int main() {
std::thread th1(print_block, 50, ‘*’);
std::thread th2(print_block, 50, ‘$’);
th1.join();
th2.join();
return 0;
}
在实际应用中,根据需要选择合适的锁和管理方法是很重要的。std::lock_guard和std::unique_lock提供了自动的锁管理功能,能够减少直接使用std::mutex时可能遇到的问题。