(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

相关文章

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

java中反射(Reflection)机制举例详解

《java中反射(Reflection)机制举例详解》Java中的反射机制是指Java程序在运行期间可以获取到一个对象的全部信息,:本文主要介绍java中反射(Reflection)机制的相关资料... 目录一、什么是反射?二、反射的用途三、获取Class对象四、Class类型的对象使用场景1五、Class

Spring Boot3虚拟线程的使用步骤详解

《SpringBoot3虚拟线程的使用步骤详解》虚拟线程是Java19中引入的一个新特性,旨在通过简化线程管理来提升应用程序的并发性能,:本文主要介绍SpringBoot3虚拟线程的使用步骤,... 目录问题根源分析解决方案验证验证实验实验1:未启用keep-alive实验2:启用keep-alive扩展建

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa

C++字符串提取和分割的多种方法

《C++字符串提取和分割的多种方法》在C++编程中,字符串处理是一个常见的任务,尤其是在需要从字符串中提取特定数据时,本文将详细探讨如何使用C++标准库中的工具来提取和分割字符串,并分析不同方法的适用... 目录1. 字符串提取的基本方法1.1 使用 std::istringstream 和 >> 操作符示

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.