std::unique_lock

1.概要

std::unique_lock

2.内容

std::unique_lock 是 C++ 标准库中的一个同步原语,它提供了对互斥锁(mutex)的独占所有权。与 std::lock_guard 类似,std::unique_lock 也用于管理互斥锁的生命周期,但它提供了更多的灵活性和功能。

主要特点和用法

  1. 灵活性:与 std::lock_guard 只能在构造时锁定互斥锁并在析构时解锁不同,std::unique_lock 允许在构造后锁定和解锁互斥锁。这意味着你可以在程序的多个点控制锁的状态。

  2. 条件变量支持std::unique_lock 常与条件变量(std::condition_variable)一起使用,因为它提供了锁定和解锁的能力,这是条件变量等待和通知机制所必需的。

  3. 超时锁定std::unique_lock 还可以尝试在一定时间内获取锁,如果在这段时间内无法获取锁,它将放弃尝试。这是通过 try_lock_for 或 try_lock_until 方法实现的。

  4. 延迟初始化:你可以创建一个未与任何互斥锁关联的 std::unique_lock 对象,然后在需要时将其与特定的互斥锁关联并锁定。

基本用法

#include <mutex>
#include <iostream>
#include <thread>

std::mutex mtx;

void print_thread_id(int id) {
    // 创建一个 unique_lock,并在构造时锁定 mtx
    std::unique_lock<std::mutex> lock(mtx);
    // 在锁的保护下执行代码
    std::cout << "线程 " << id << std::endl;
    // unique_lock 的析构函数会自动解锁
}

int main() {
    std::thread t1(print_thread_id, 1);
    std::thread t2(print_thread_id, 2);

    t1.join();
    t2.join();

    return 0;
}

在这个例子中,std::unique_lock<std::mutex> lock(mtx); 在构造时锁定了互斥锁 mtx,并在其析构时自动解锁,确保了线程安全的打印操作。

高级用法

std::unique_lock<std::mutex> lock(mtx, std::defer_lock);
// 在需要时锁定
lock.lock();
// 执行一些操作
// 显式解锁
lock.unlock();

在这个高级用法中,std::defer_lock 参数指示 std::unique_lock 在构造时不锁定互斥锁。然后,你可以在代码的适当位置调用 lock.lock() 和 lock.unlock() 来控制锁的状态。

总之,std::unique_lock 提供了一个灵活且强大的方式来管理互斥锁的生命周期,是编写多线程程序时的一个重要工具。

3.关联链接

std::unique_lock-优快云博客

std::condition_variable-优快云博客 

std::future和std::promise-优快云博客 

gnome-session-properties-优快云博客 

4.关联知识 

### `std::unique_lock` 的用法与常见错误 `std::unique_lock` 是 C++ 标准库中用于管理互斥锁的通用机制之一,相较于 `std::lock_guard`,它提供了更灵活的锁定策略,包括延迟锁定、尝试锁定、超时锁定以及手动解锁等功能。`std::unique_lock` 通常用于需要更精细控制锁生命周期的场景,例如条件变量的等待操作。 #### 基本用法 `std::unique_lock` 的基本构造方式如下: ```cpp std::mutex mtx; std::unique_lock<std::mutex> lock(mtx); ``` 上述代码构造了一个 `std::unique_lock` 实例,并在构造时锁定关联的互斥量 `mtx`。若希望延迟锁定,可使用如下方式: ```cpp std::unique_lock<std::mutex> lock(mtx, std::defer_lock); lock.lock(); // 手动加锁 ``` 这种方式适用于需要在特定条件下加锁的场景。 #### 与条件变量结合使用 `std::unique_lock` 常与 `std::condition_variable` 配合使用,以实现线程间的同步。例如: ```cpp std::mutex mtx; std::condition_variable cv; bool ready = false; void wait_for_ready() { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, []{ return ready; }); // 继续执行 } void set_ready() { std::lock_guard<std::mutex> lock(mtx); ready = true; cv.notify_all(); } ``` 该模式广泛应用于多线程任务调度、生产者-消费者模型等并发场景[^1]。 #### 常见错误 1. **未指定模板参数** 若直接声明 `std::unique_lock` 而未指定模板参数,例如: ```cpp std::unique_lock lock; // 错误:缺少模板参数 ``` 将导致编译错误 `missing template arguments before 'lock'`。正确用法应为: ```cpp std::unique_lock<std::mutex> lock(mtx); ``` 2. **重复解锁** `std::unique_lock` 在析构时会自动解锁其持有的互斥量。若手动调用 `.unlock()` 后再次析构,可能导致未定义行为。 3. **跨函数传递未释放锁** 若将 `std::unique_lock` 实例作为参数传递给其他函数而未释放所有权,可能导致锁的持有时间超出预期,影响并发性能。 4. **未正确处理异常** 若在加锁后抛出异常,但未使用 `std::unique_lock` 管理锁的生命周期,可能造成死锁。 #### 使用 `std::shared_mutex` 的写锁 `std::unique_lock` 也可用于 `std::shared_mutex` 的写锁操作,例如: ```cpp std::shared_mutex rw_mutex; void writer() { std::unique_lock<std::shared_mutex> lock(rw_mutex); // 写操作 } ``` 该方式确保在写操作期间没有其他读线程或写线程访问资源。 #### 总结 `std::unique_lock` 提供了比 `std::lock_guard` 更灵活的锁管理机制,适用于需要手动控制加锁、解锁时机的并发场景。合理使用该机制可提升程序的并发性能与安全性,但需注意模板参数缺失、重复解锁、异常处理等常见问题。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值