C++ 并发编程,std::unique_lock与std::lock_guard区别示例

2024-03-30 20:08

本文主要是介绍C++ 并发编程,std::unique_lock与std::lock_guard区别示例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

平时看代码时,也会使用到std::lock_guard,但是std::unique_lock用的比较少。在看并发编程,这里总结一下。方便后续使用。

std::unique_lock也可以提供自动加锁、解锁功能,比std::lock_guard更加灵活。

std::lock_guard

std::lock_guard是RAII模板类的简单实现,功能简单。

1.std::lock_guard 在构造函数中进行加锁,析构函数中进行解锁。
2.锁在多线程编程中,使用较多,因此c++11提供了lock_guard模板类;在实际编程中,我们也可以根据自己的场景编写resource_guard RAII类,避免忘掉释放资源。

下面是一个使用std::lock_guard的代码例子,1+2+ .. + 100的多线程实现,每个num只能由一个线程处理。:

#include <thread>
#include <mutex>
#include <vector>
#include <iostream>
#include <algorithm>std::mutex my_lock;void add(int &num, int &sum){while(true){std::lock_guard<std::mutex> lock(my_lock);  if (num < 100){ //运行条件num += 1;sum += num;}   else {  //退出条件break;}   }   
}int main(){int sum = 0;int num = 0;std::vector<std::thread> ver;   //保存线程的vectorfor(int i = 0; i < 20; ++i){std::thread t = std::thread(add, std::ref(num), std::ref(sum));ver.emplace_back(std::move(t)); //保存线程}   std::for_each(ver.begin(), ver.end(), std::mem_fn(&std::thread::join)); //joinstd::cout << sum << std::endl;
}

std::unique_lock

类 unique_lock 是通用互斥包装器,允许延迟锁定、锁定的有时限尝试、递归锁定、所有权转移和与条件变量一同使用
unique_lock比lock_guard使用更加灵活,功能更加强大。
使用unique_lock需要付出更多的时间、性能成本。

下面是try_lock的使用例子。

#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <mutex>          // std::mutex, std::unique_lock
#include <vector>std::mutex mtx;           // mutex for critical section
std::once_flag flag;void print_block (int n, char c) {//unique_lock有多组构造函数, 这里std::defer_lock不设置锁状态std::unique_lock<std::mutex> my_lock (mtx, std::defer_lock);//尝试加锁, 如果加锁成功则执行//(适合定时执行一个job的场景, 一个线程执行就可以, 可以用更新时间戳辅助)if(my_lock.try_lock()){for (int i=0; i<n; ++i)std::cout << c;std::cout << '\n';}
}void run_one(int &n){std::call_once(flag, [&n]{n=n+1;}); //只执行一次, 适合延迟加载; 多线程static变量情况
}int main () {std::vector<std::thread> ver;int num = 0;for (auto i = 0; i < 10; ++i){ver.emplace_back(print_block,50,'*');ver.emplace_back(run_one, std::ref(num));}for (auto &t : ver){t.join();}std::cout << num << std::endl;return 0;
}

转载自:C++ 并发编程,std::unique_lock与std::lock_guard区别示例 - 旭东的博客 - 博客园

这篇关于C++ 并发编程,std::unique_lock与std::lock_guard区别示例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/862452

相关文章

Spring Boot中的路径变量示例详解

《SpringBoot中的路径变量示例详解》SpringBoot中PathVariable通过@PathVariable注解实现URL参数与方法参数绑定,支持多参数接收、类型转换、可选参数、默认值及... 目录一. 基本用法与参数映射1.路径定义2.参数绑定&nhttp://www.chinasem.cnbs

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

PostgreSQL中rank()窗口函数实用指南与示例

《PostgreSQL中rank()窗口函数实用指南与示例》在数据分析和数据库管理中,经常需要对数据进行排名操作,PostgreSQL提供了强大的窗口函数rank(),可以方便地对结果集中的行进行排名... 目录一、rank()函数简介二、基础示例:部门内员工薪资排名示例数据排名查询三、高级应用示例1. 每

MyBatis中$与#的区别解析

《MyBatis中$与#的区别解析》文章浏览阅读314次,点赞4次,收藏6次。MyBatis使用#{}作为参数占位符时,会创建预处理语句(PreparedStatement),并将参数值作为预处理语句... 目录一、介绍二、sql注入风险实例一、介绍#(井号):MyBATis使用#{}作为参数占位符时,会

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab