(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

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)