C++11 新特性:锁
在多线程编程中,锁是用于控制对共享资源的访问的一种机制。C++11 引入了一系列新特性来支持线程同步,提供了更高效、更安全的锁管理。本文将介绍 C++11 中的三种重要锁类:std::mutex、std::lock_guard 和 std::unique_lock,以及它们的使用方法和特点。
1. std::mutex
std::mutex 是 C++11 引入的标准互斥锁,用于保护共享资源,防止多个线程同时访问引发的数据竞争。std::mutex 提供了基本的锁功能,允许一个线程独占对共享资源的访问权。
示例:
#include <iostream>#include <thread>#include <mutex>std::mutex mtx;void print_message(const std::string& message) { std::lock_guard<std::mutex> lock(mtx); // 加锁 std::cout << message << std::endl;}在这个示例中,std::mutex 对象 mtx 用于保护 print_message 函数中的 std::cout,确保同一时间只有一个线程可以打印消息。
2. std::lock_guard
std::lock_guard 是一种基于 RAII(资源获取即初始化) 的简单锁管理器。它在构造时自动获取锁,在作用域结束时自动释放锁,确保锁在临界区内被正确持有和释放。
示例:
#include <iostream>#include <thread>#include <mutex>std::mutex mtx;void example() { std::lock_guard<std::mutex> lock(mtx); // 自动加锁 // 临界区操作 std::cout << "In critical section" << std::endl;} // lock 离开作用域时自动解锁在这个示例中,std::lock_guard 对象 lock 在创建时自动加锁,离开作用域时自动解锁,简化了锁的管理。
3. std::unique_lock
std::unique_lock 是一个更灵活的锁管理器,相比 std::lock_guard,它支持延迟加锁、手动解锁和条件变量等功能,适用于更复杂的锁控制场景。
主要功能:
-
延迟加锁:可以在创建时不立即加锁,稍后通过
lock()方法手动加锁。 -
显式解锁:可以通过
unlock()方法手动解锁,允许在需要时提前释放锁。 -
所有权转移:支持通过
std::move将锁的所有权从一个std::unique_lock实例转移到另一个。
示例:
延迟加锁
#include <iostream>#include <thread>#include <mutex>std::mutex mtx;void example() { std::unique_lock<std::mutex> lock(mtx, std::defer_lock); // 延迟加锁 lock.lock(); // 手动加锁 // 临界区操作 std::cout << "In critical section" << std::endl; lock.unlock(); // 手动解锁} // lock 离开作用域时自动解锁在这个示例中,std::unique_lock 被初始化为延迟加锁,锁在需要时显式加锁和解锁。
锁的所有权转移
#include <iostream>#include <thread>#include <mutex>void func(std::unique_lock<std::mutex> lock) { // lock 持有互斥锁 std::cout << "In critical section in func" << std::endl;} // lock 离开作用域时解锁int main() { std::mutex mtx; std::unique_lock<std::mutex> lock(mtx); // 加锁 func(std::move(lock)); // 将锁的所有权转移到 func // lock 在这里是将亡值,已经不再持有锁}在这个示例中,std::move(lock) 将锁的所有权传递给 func 函数。func 函数在其作用域内持有锁,main 函数中的 lock 变成将亡值,不能再使用。
总结
C++11 引入的锁机制使多线程编程变得更加简单和安全:
-
std::mutex提供基本的互斥功能,用于保护共享资源。 -
std::lock_guard基于 RAII 机制,简化了锁的管理,确保在作用域内持有锁。 -
std::unique_lock提供了更高的灵活性,支持延迟加锁、手动解锁和锁所有权转移,适用于更复杂的锁控制需求。
了解这些新特性,并根据实际需要选择合适的锁管理方式,将帮助你在多线程编程中更有效地管理共享资源和确保线程安全。