(leetcode1114) C++11线程同步机制(源码粗读)

2023-11-23 01:40

本文主要是介绍(leetcode1114) C++11线程同步机制(源码粗读),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

线程同步

同步,顾名思义就是齐步并进。异步,就是两个人各走各的不管对方。两个同步的线程要时不时停下来等等对方,比如说一个线程负责读磁盘、另一个线程负责解析文件内容,那么解析文件内容的线程就要等都读磁盘的线程把内容读出来才能解析。而异步的两个线程各自干自己的工作,不会因为对方状况而阻塞。

在实际工作中总是会需要一些并发的操作,比如最基本的,服务器总要同时维持很多连接吧。
比如你要记录当前的连接数,那么就要有一个全局的cnt,来一个连接就cnt++,断一个连接就cnt–。

但是在汇编层面cnt++这个操作可能长这样(我这里写的是mips):

lw $t1, 8($t0)
addi $t1, $t1, 1
sw $ t1, 8($t0)

所以到机器层面上一共要执行三条指令,万一执行到一半的时候因为什么中断切出去了(比如时钟中断之后直接进行了线程切换),那么这个被取出的cnt值就会随着换出的上下文被存起来,这个时候如果另一个指令又执行了cnt++,然后再切回来的时候,+1操作就成了基于原先的cnt而不是最新的cnt。所以最后cnt的值就比实际的要小。

解决这个问题的方法就是引入一些同步机制。比如互斥锁mutex,或者信号量semaphore。这些东西最终在机器层面上都是有支持的,比如可以设计一种不会被打断的一种原子操作,所谓原子操作就是不会切换上下文,处理器可以执行一条关中断的指令来暂时屏蔽中断来达成这种效果。

具体在硬件层面的东西我不是很熟悉,我只是个程序员,今天我想从软件层面上探索一下C++的stl库里实现的一些同步机制。

我用这个网站来测试我的程序:https://leetcode-cn.com/problems/print-in-order/submissions/

mutex

mutex这个词是从mutal exclusive造出来的,意思是互斥。假设有好几个线程尝试对其上锁,那么第一个上锁操作会成功,后面对其上锁的线程会被阻塞。当该锁被解锁的时候,被阻塞的线程的其中一个会被唤醒,并且该锁再次被上锁。所以同一时间只能由某一个线程拥有该锁,如果你把锁放在互斥代码段的开头和结尾,就相当同时只有一个线程能够执行互斥代码。
在这里插入图片描述
构造函数是无参的,然后lock函数是阻塞式的,try_lock是非阻塞式的,非阻塞式的方法返回一个bool值表示加锁是否成功。unclock就是解锁,文档说如果对未上锁的锁进行unlock是未定义的行为。

以下代码是在leetcode1114上可以通过测试的,这份代码依次打印first,second,third

class Foo {
public:std::mutex m2, m3;Foo() {m2.lock();m3.lock();}void first(function<void()> printFirst) {// printFirst() outputs "first". Do not change or remove this line.printFirst();m2.unlock();}void second(function<void()> printSecond) {// printSecond() outputs "second". Do not change or remove this line.m2.lock();printSecond();m3

这篇关于(leetcode1114) C++11线程同步机制(源码粗读)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

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

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

C++中assign函数的使用

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

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

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

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

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

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

C++中NULL与nullptr的区别小结

《C++中NULL与nullptr的区别小结》本文介绍了C++编程中NULL与nullptr的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编... 目录C++98空值——NULLC++11空值——nullptr区别对比示例 C++98空值——NUL

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window