C++11并发与多线程笔记(6) unique_lock(类模板)

这篇具有很好参考价值的文章主要介绍了C++11并发与多线程笔记(6) unique_lock(类模板)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、unique_lock取代lock_guard

unique_lock 是一个类模板。
unique_lock 比 lock_guard 灵活很多多出来很多用法),效率差一点,内存占用多一些。
使用:
unique_lock<mutex> myUniLock(myMutex);

2、unique_lock的第二个参数

2.1 std::adopt_lock:

std::adopt_lock:标记作用,表示这个互斥量已经被lock()(方便记忆:已经被lock()收养了,不需要再次lock() ),即不需要在构造函数中lock这个互斥量了。
前提必须提前lock,否则会出错
lock_guard中也可以用这个参数

2.2 std::try_to_lock:

  • 尝试用mutex的lock()去锁定这个mutex,但如果没有锁定成功,会立即返回,不会阻塞在那里
  • 使用try_to_lock的原因是防止其他的线程锁定mutex太长时间,导致本线程一直阻塞在lock 这个地方
    前提不能提前lock();
    owns_lock()方法判断是否拿到锁,如拿到返回true
    实例:
    假设
    线程1 执行下例代码时,先锁定互斥量myMutex1
    ,然后暂停了2s,才继续执行程序。线程1执行的代码如下
bool outMsgProc(int &num)
{
	unique_lock<mutex> muGuard(myMutex1);
	chrono::milliseconds time(2000);    //线程暂停2s
	this_thread::sleep_for(time);
	if (!myList.empty())
	{
		num = myList.front();
		myList.pop_front();
		return true;
	}
	return false;
}

在此期间,如果线程2也尝试锁定myMutex1,就只能阻塞,直到线程1释放锁后,才能继续执行。线程2执行的代码如下:

void InMsg()
{
	for (int i = 0; i < 10000; i++)
	{
		cout << "插入元素: " << i << endl;
		unique_lock<mutex> muGuard(myMutex1);
		myList.push_back(i);			
	}
}

显然,这样的程序效率不高。线程2花费了太多的时间等待。

我们考虑使用try_to_lock,线程尝试获取锁,如果没有锁定成功,它不会阻塞在那里,可以去执行其他代码。改进后的代码如下:

void InMsg()
{
	for (int i = 0; i < 10000; i++)
	{
		cout << "插入元素: " << i << endl;
		unique_lock<mutex> muGuard(myMutex1, try_to_lock);
		if (muGuard.owns_lock())// 判断是否拿到锁
		{
			myList.push_back(i);
		}
		else
		{
			//没有拿到锁时,执行的代码
		}
	}
}

2.3 std::defer_lock:

  • 如果没有第二个参数就对mutex进行加锁,加上defer_lock是始化了一个没有加锁的mutex
  • 不给它加锁的目的是以后可以调用unique_lock的一些方法
  • 前提不能提前lock

3、unique_lock的成员函数(前三个与std::defer_lock联合使用)

3.1 lock():加锁。

unique_lock<mutex> muGuard(myMutex, defer_lock);
muGuard.lock();//手动加锁

不用自己unlock();

3.2 unlock():解锁。

unique_lock<mutex> muGuard(myMutex, defer_lock);
muGuard.lock();
//处理一些共享代码
muGuard.unlock();
//临时处理一些非共享代码
muGuard.lock();
//处理一些共享代码,处理完之后,自动解锁

3.3 try_lock():尝试给互斥量加锁

try_to_lock是unique_lock的第二个参数,try_lock()是unique_lock()的成员变量。
如果拿不到锁,返回false,否则返回true(然后上锁)。

 unique_lock<mutex>muGuard(myMutex, defer_lock);
 //mutex1.lock();//自动解锁
 if (muGuard.try_lock() == true) {
     cout << "插入数据: " << num << endl;
     test_list.push_back(num);
 }
 else {
     cout << "in_list()执行,但没有拿到锁" << num << endl;
 }

3.4 release():

release():就是解除绑定,返回它所管理的mutex对象的指针,并释放所有权。

  1. unique_lock<mutex>muGuard(myMutex1);
    相当于把myMutex(mutex对象)和 muGuard绑定在了一起
  2. mutex* ptx =muGuard.release();
    也就是说 muGuard和mutex不在有联系,后续myMutex所有权由ptx接管,如果原来mutex对象处理加锁状态,就需要ptx在以后进行解锁了。
for (int num = 0; num < 10000; num++) {
    unique_lock<mutex> muGuard(myMutex);
    mutex* ptx = muGuard.release();//解除myMutex1(mutex对象)和 muGuard绑定
    //操作事务
    test_list.push_back(num);
    ptx->unlock();//myMutex1所有权由ptx接管,由ptx进行解锁
}

lock的代码段越少,执行越快,整个程序的运行效率越高。

  • 锁住的代码少,叫做粒度细,执行效率
  • 锁住的代码多,叫做粒度粗,执行效率
    -只锁定共享的数据

4.unique_lock所有权的传递

unique_lock<mutex> muGuard1(myMutex);
把myMutex1和muGuard绑定在了一起,也就是muGuard拥有myMutex1的所有权

4.1 使用move转移

unique_lock<mutex> muGuard2(std::move(muGuard1));
之前muGuard1拥有myMutex的所有权,muGuard1可以把自己对myMutex的所有权转移,但是不能复制。现在muGuard2拥有myMutex的所有权。文章来源地址https://www.toymoban.com/news/detail-655872.html

4.2. 在函数中return一个临时变量,也可以实现转移

unique_lock<mutex> aFunction()
{
    unique_lock<mutex> tmpguard(myMutex);
    //移动构造函数那里讲从函数返回一个局部的unique_lock对象是可以的
    //返回这种局部对象会导致系统生成临时的unique_lock对象,并调用unique_lock的移动构造函数
    return tmpguard;
}
// 然后就可以在外层调用,在muGuard2具有对myMutex的所有权
std::unique_lock<std::mutex> muGuard2 = aFunction();

到了这里,关于C++11并发与多线程笔记(6) unique_lock(类模板)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++11并发与多线程笔记(10) future其他成员函数、shared_future、atomic

    status = result.wait_for(std::chrono::seconds(几秒)); 卡住当前流程,等待std::async()的异步任务运 行一段时间,然后返回其状态std::future_status 。如果std::async()的参数是std::launch::deferred(延迟执行),则不会卡住主流程。 std::future_status是枚举类型,表示异步任务的执行状态。类型的取值

    2024年02月12日
    浏览(30)
  • C++11并发与多线程笔记(7) 单例设计模式共享数据分析、解决,call_once

    程序灵活,维护起来可能方便,用设计模式理念写出来的代码很晦涩,但是别人接管、阅读代码都会很痛苦 老外应付特别大的项目时,把项目的开发经验、模块划分经验,总结整理成设计模式 中国零几年设计模式刚开始火时,总喜欢拿一个设计模式往上套,导致一个小小的

    2024年02月12日
    浏览(31)
  • C++并发与多线程笔记八:async、future、packaged_task、promise

    本文接上文 C++并发与多线程笔记七:condition_variable、wait、notify_one/all 的内容,主要记录 async、future、packaged_task、promise 概念以及用法。 2.1 基本用法 std::async 是个函数模板,用来启动一个异步任务,启动一个异步任务后,它返回一个 std::future 类模板对象。 上述\\\"启动一个异步

    2023年04月13日
    浏览(38)
  • 分布式集群与多线程高并发

      后台数据的处理语言有很多,Java 是对前端采集的数据的一种比较常见的开发语言。互联网移动客户端的用户量特别大,大量的数据处理需求应运而生。可移动嵌入式设备的表现形式   很多,如 PC 端,手机移动端,智能手表,Google  眼镜等。Server2client 的互联网开发模式比

    2024年02月08日
    浏览(39)
  • Python中的并发编程:多线程与多进程的比较【第124篇—多线程与多进程的比较】

    在Python编程领域中,处理并发任务是提高程序性能的关键之一。本文将探讨Python中两种常见的并发编程方式:多线程和多进程,并比较它们的优劣之处。通过代码实例和详细的解析,我们将深入了解这两种方法的适用场景和潜在问题。 多线程是一种轻量级的并发处理方式,适

    2024年03月14日
    浏览(68)
  • 【linux 多线程并发】多线程模型下的信号通信处理,与多进程处理的比较,属于相同进程的线程信号分发机制

    ​ 专栏内容 : 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况下对故障容灾的支持。 手写数据库toadb 本专栏主要介绍如何从零开发,开发的

    2024年01月17日
    浏览(35)
  • 【Java基础教程】(四十二)多线程篇 · 上:多进程与多线程、并发与并行的关系,多线程的实现方式、线程流转状态、常用操作方法解析~

    理解进程与线程的区别; 掌握Java 中多线程的两种实现方式及区别; 掌握线程的基本操作方法; 进程是程序的一次动态执行过程,它经历了从代码加载、执行到执行完毕的一个完整过程,这个过程也是进程本身从产生、发展到最终消亡的过程 。多进程操作系统能同时运行多

    2024年02月16日
    浏览(38)
  • JUC并发编程-线程和进程、Synchronized 和 Lock、生产者和消费者问题

    源码 + 官方文档 面试高频问! java.util 工具包、包、分类 业务:普通的线程代码 Thread Runnable Runnable 没有返回值、效率相比入 Callable 相对较低! 线程、进程,如果不能使用一句话说出来的技术,不扎实! 进程:一个程序,QQ.exe Music.exe 程序的集合; 一个进程往往可以包含多

    2024年01月20日
    浏览(39)
  • JUC并发编程学习笔记(二)Lock锁(重点)

    传统的synchronized 传统的解决多线程并发导致的一些问题我们会使用synchronized来解决,synchronized的本质就是队列、锁。 Lock的实现类有:可重复锁(最常用)、读锁、写锁 在创建可重复锁时,可传入boolean类型值来决定该锁是公平锁(先来后到)还是非公平锁(可插队)

    2024年02月06日
    浏览(31)
  • 《C++并发编程实战》读书笔记(1):线程管控

    包含头文件 thread 后,通过构建 std::thread 对象启动线程,任何可调用类型都适用于 std::thread 。 启动线程后,需要明确是等待它结束、还是任由它独自运行: 调用成员函数 join() 会先等待线程结束,然后隶属于该线程的任何存储空间都会被清除, std::thread 对象不再关联到已结

    2024年02月10日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包