多线程,异步、同步,互斥量和锁

多线程,异步、同步,互斥量和锁
使用库来创建和管理线程。

使用创建互斥锁,并通过使用lock_guard或unique_lock类来管理互斥锁。

使用来实现原子操作

使用<conditional_variable>来使用条件变量

常见互斥锁
  • std::mutex:最基本的互斥锁类型,一次只允许一个线程拥有锁。
  • std::recursive_mutex:允许同一个线程多次递归地锁定和解锁同一个互斥锁。
  • std::timed_mutex:支持带超时的锁定操作的互斥锁。
lock_guard

std::lock_guard 是 C++ 标准库中的一个模板类,它的设计目的是自动管理互斥锁的锁定和解锁操作。std::lock_guard 的模板参数是互斥锁的类型,以下是一些常见的互斥锁类型:

  • std::mutex:最基本的互斥锁类型,一次只允许一个线程拥有锁。
  • std::recursive_mutex:允许同一个线程多次递归地锁定和解锁同一个互斥锁。
  • std::timed_mutex:支持带超时的锁定操作的互斥锁。

std::lock_guard 的实例化语法如下:

std::lock_guard<Mutex> lock_guard_instance(mutex_instance);

这里,Mutex 是互斥锁的类型,mutex_instance 是互斥锁的一个具体实例。

std::lock_guard是一个模板类。在构造时自动获取锁,并在析构时自动释放锁,从而避免了因异常或早期返回导致的死锁问题。

注意:lock_guard不能手动进行锁的锁定和释放。

lock_guard能够处理临界区的问题

#include <mutex>
#include <iostream>

std::mutex mtx;

void safe_print(int value) {
    std::lock_guard<std::mutex> lk(mtx);
    // 临界区开始
    std::cout << "Printed value: " << value << std::endl;
    // 临界区结束,lk 在这里自动析构并释放锁
}

int main() {
    safe_print(10);
    safe_print(20);
    return 0;
}

lock_guard能够接收第二个参数,例如std::adopt_lock。

adopt_lock表示这个互斥量已经锁定了(需要提前将互斥量锁定,否则会报错)

临界区:

临界区(Critical Section) 保证在某一时刻只有一个线程能访问数据的简便办法。其只能用于对象在同一进程里线程间的互斥访问。

unique_lock

unique_lock也是一个类模板,模板参数也是Mutex互斥锁。其与lock_guard的区别有:

  • unique_lock能够转移mutex,而lock_guard不能;[注意:虽然能够转移mutex的所有权,但是不能够复制]

  • unique_lock可以执行手动锁定和解锁的操作,而lock_guard不能;

unique_lock可以接收的第二个参数:

  • adopt_lock:标记互斥量已经加锁了

  • defer_lock:标记一个没有加锁的互斥量。即初始化一个没有加锁的mutex。

  • try_to_lock:尝试使用mutex的lock()去锁定这个mutex,如果没有锁定成功,返回false,函数不阻塞。

unique_lock的成员方法:

  • lock():加锁

  • unlock():解锁

  • try_lock():尝试给互斥量加锁,如果拿不到锁,返回flase;如果拿到了锁,返回true。此函数不阻塞。

  • release():返回管理的mutex对象指针,并释放所有权。如果原来mutex对象处于加锁状态,需要自己负责手动解锁。

conditional_variable

conditional_variable类是条件变量。当 std::condition_variable 对象的某个 wait 函数被调用的时候,它使用 std::unique_lock(通过 std::mutex) 来锁住当前线程。当前线程会一直被阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程。

std::condition_variable 对象通常使用 std::unique_lock<std::mutex>来等待,如果需要使用另外的 lockable 类型,可以使用 std::condition_variable_any 类。

锁的粒度

锁定区域的大小称为锁的粒度,锁定范围大称为粗粒度,锁定范围小称为细粒度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值