- 博客(78)
- 收藏
- 关注
原创 线程互斥补全和加锁原理
可是此时寄存器内已经是0,它交换之后会做判断,如果是大于0,就执行,等于0,就挂起等待。操作时,以一条汇编指令的形式交换寄存器和内存单元中的数据,将寄存器的1和a来交换。为了方便理解,我们把锁简单理解成包含整形1的一个结构体,在内存单元中。要解决饥饿问题,就要使多线程执行有一定顺序性,也就是线程同步。多线程运行时,一份资源,有进程长期无法拥有,造成饥饿问题。可以定义上面这样的类,自动析构就等于解锁,非常方便。如果这时线程时间片到了,第二个线程过来,也要交换。互斥锁可以是全局的,也可以像上面一样是局部的。
2024-04-19 15:31:55
331
原创 线程互斥及基于线程锁的抢票程序
根据互斥的定义,任何一个时刻只允许一个线程申请锁成功,申请失败的进程在mutex阻塞,本质就是等待。任何时刻,互斥保证只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用。首先把a从内存拷贝到CPU的寄存器,字CPU中完成++操作,再返回内存,不是原子的。可能大家会认为,当线程进入锁,执行锁内代码,这是如果发生切换,还是会产生同样的错误。其实这次不一样了,因为就算时间片到了,发生线程切换,被切换到的线程也没办法访问锁。申请锁本身是原子的,有宝马。就相当于上的线程的密码锁,专属的。
2024-04-18 22:24:33
885
原创 C++的线程
这样,我们学习别的语言,只需要学习接口,因为我们知道底层是一样的。用纯c++的接口创建线程时,在Linux中还是要包含线程库。这说明c++的那些库本质就是pthread原生线程库的封装。在编译链接库时,就会给每一个变量在线程局部存储中开辟空间。__thread可以给每个执行流一个变量。如果不添加-lpthread就会报错。说到底,这样的设计就是为了跨平台性。接下来了解一下线程的局部存储。下面是多线程的一个简单模版。
2024-04-18 13:37:05
383
原创 线程控制及线程底层原理
默认地址空间中的栈由主线程使用,这样,可以保证每一个新线程都可以保存要执行的方法,要传递的参数以及动态运行时的临时变量。同样的,pthread库也是库,在库中实现pthread_create的时候,内部包的就是clone函数。创建线程的时候,在正文代码区,直接跳转到共享区的库里,执行创建线程的函数,然后返回。7、用户栈:线程执行的用户方法栈,用来保存线程当前执行的用户方法的信息。而线程库是共享的,所以,内部要管理整个系统,多个用户启动的所有的线程。
2024-04-17 20:51:26
671
原创 多线程传参以及线程的优缺点
如果计算密集型 线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的 同步和调度开销,而可用的资源不变。linux没有真线程,只有轻量化进程,所以Linux OS只会提供轻量化进程的系统调用,不会直接提供线程创建的接口。编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了。与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多。而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。然后在软件层中,将线程对应成LWP。
2024-04-16 20:16:15
1022
原创 什么是线程?线程和进程谁更弔?
线程较进程更轻量化,调度上来说,pcb切换另一个pcb,地址空间,页表等是不用切换的,只需更换进程运行中寄存器产生的临时数据。线程的本质就是CPU调度的基本代码,Linux内核复用了进程代码,用进程pcb模拟充当线程。操作系统调度的时候,看的也是lwp,判断是主线程还是新线程,看的是lwp是否等于pid。换句话说,线程切换时,不需要切换CPU内部的所有寄存器的数据,而只需更换少部分。cache会对用户操作做出预判,加以缓存,大概率猜对,猜不对也没关系,重新缓存。
2024-04-16 00:58:34
608
原创 从零带你底层实现unordered_map的代码补全(2)
先把代码发出来,大家先看,有什么不懂得都可以私信问我。这块的迭代器是比较复杂,需要仔细看看。有问题题请私信 😘 😘 😘。
2023-12-04 12:41:19
771
4
原创 从零带你底层实现unordered_map (2)
💯 博客内容:从零带你实现unordered_map😀 作 者:陈大大陈🚀 个人简介:一个正在努力学技术的准C++后端工程师,专注基础和实战分享 ,欢迎私信!💖 欢迎大家:这里是CSDN,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘哈希/散列:映射,关键字和另一个值建立一个关联关系。哈希表/散列表:映射,关键字和储存位置建立一个关联关系。哈希/散列是一种算法思想,而哈希表/散列表是基于这种算法思想而实现的一种数据结构,这点很容易混淆。上一篇博客介绍了两个解决哈希冲突的方法,
2023-11-28 14:20:30
1287
22
原创 从零带你底层实现unordered_map (1)
它是一个单向的迭代器。为什么专门提到这个呢?因为这是我踩过坑的地方!!单向迭代器压根就不能使用sort函数来排序!std::unordered_map的迭代器类型是ForwardIterator,而不是sort函数要求的RandomAccessIterator,这里不符合。我们要排序的话,还是将unordered_map里存的值,转存到vector里面。然后我们再自定义一个排序方法,对vector进行排序。
2023-11-20 23:08:47
1004
19
原创 并查集模版以及两道例题
上面的时间复杂度最好能有O(1)。实现方式是记忆化搜索,用数组存储好所需结果,需要时就不用再次递归了。这种并查集查找的效率太低,最坏情况的时间复杂度能达到O(N)。我们就针对它优化。上面的时间复杂度最好能有O(1)。实现方式是记忆化搜索,用数组存储好所需结果,需要时就不用再次递归了。来看两个例题巩固一下。How Many Tables(并查集)Problem - 1213 (hdu.edu.cn)题目:Today is
2023-11-06 19:45:15
399
27
原创 多态 多继承的虚表深度剖析 (3)
这么打印,需要注意的是,d是一个Derive类,加一的话会加上一个Derive的大小。我没看到,编译器仍旧是故技重施,欺骗我们的眼睛,我们检测监测不到func3。但是这样的话,就会衍生出一个问题,它自己的虚函数也就是func3放在哪里呢?此时有看起来有3个虚表,其实还是2个。答案是,因为继承了Base1和Base2两个类,所以有两个虚表。上面这种多继承的情况,Derive有几个虚表呢?我们得到结论,func3放到了第一个虚表里面。答案是两张,这种情况就跟普通的多继承没两样。还可以这样写,最聪明的一种写法。
2023-11-05 22:08:45
1357
23
原创 多态 虚函数表深度剖析 纯干货讲解(2)
打开内存监视窗口,我们高度怀疑后面两个地址是被隐藏的两个虚函数的地址。虚函数和普通函数一样,存在代码段,同时将虚函数地址存了一份到虚函数表。第一次编译器出了bug,没有在虚表后标识上0,第二次就好了。终于到了放终结技的时候了,我们可以在打印的时候同时调用函数。上面我们埋下了伏笔,在命令行窗口会打印出来调用函数的信息。经过测试,虚表是储存在常量区的代码段的,跟常量很接近。虚表储存在类的前四个字节,我们就取这四个字节打印出来。并不是这样,监视窗口看到的内容是经过编译器处理的。看不明白的老铁可以看看上面的图。
2023-11-05 18:01:27
203
12
原创 C++ 多态 纯干货讲解 复制可调试(1)
从上面可以看出,C++对函数重写的要求比较严格,但是有些情况下由于疏忽,可能会导致函数名字母次序写反而无法构成重载,而这种错误在编译期间是不会报出的,只有在程序运行时没有得到预期结果才来debug会得不偿失,因此:C++11提供了override和final两个关键字,可以帮助用户检测是否重写。调用指针或者引用指向的对象,指向父类就调用父类,指向子类就调用子类。查找虚函数表中存储的地址,是父类就调用父类,是子类就切割成父类对象。答案是B,容易选成D,需要注意的是,虚函数继承声明,重写实现。
2023-11-04 22:50:11
248
16
原创 关于刷题时使用数组的小注意事项
在Windows下,栈的大小为2M,也就是1024*1024*2 = 2097152个字节。所有我们在程序中声明局部变量时(在栈区),最好不好超过int[200000]的内存变量。总之,当程序需要声明一个超过十万级的变量时,最好放在main函数外面,作为全局变量去使用。不然的话,可能像我上面那样发生栈溢出问题,还以为是代码的思路有问题。对于c语言,一个静态数组能有多大,取决于剩余内存的空间,也就是它所在区的大小;全局数组是存储在内存中的静态区,而局部变量是存储在栈区。
2023-10-20 12:00:53
385
18
原创 (面试)谈谈我对C++面向对象特性的理解
总的来说,面向对象是一种方法,这种方法是用来组织设计和实现的。组织设计就是找到解决问题的思路。实现就是把代码写出来。面向对象关键的核心在于,对象是组织和实现主要关注的东西,而不是过程。
2023-10-07 20:10:03
918
21
原创 C++的范围for语句详解 附易错实例
在范围for语句中定义的变量,容器或者数组内的每个元素都必须能转换成该变量的类型。实例2:将字符串中所有的大写字母转化成小写字母,将所有的小写字母转化成大写字母。但是有一点要特别注意,刚才举的例子中的变量i实质是数组a中每个元素的。如果仅是修改变量i的值,数组a中的元素的值是不会变化的。范围for语句是C++引入的一个语法糖,例如,下面的代码让数组中每一个元素加三。这么一看还是范围for语句比较简洁。如果要通过变量i修改数组中变量的值,所有的元素都处理完毕后循环终止。让编译器帮助制定合适的类型。
2023-07-09 17:23:20
740
11
原创 C++的auto类型说明符详解 附易错实例
C++里没有越界检测机制,即使正整数的值已经超过了字符串的长度,循环体依旧可以成功运行。所以程序会莫名其妙的输出乱码。而且,即使i从正整数值递减到0,依然会因为刚才解释的原因再次回到那个非常大的正整数值。所以程序是一个死循环。要解决死循环也非常简单。
2023-07-08 21:49:14
1195
45
原创 C++ string中内置的字符串操作和标准库中常用字符处理函数
💯 博客内容:C++读取一行内个数不定的整数的方式😀 作 者:陈大大陈🚀 个人简介:一个正在努力学技术的准前端,专注基础和实战分享 ,欢迎私信!💖 欢迎大家:这里是CSDN,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘 😘 😘string中定义了求字符串长度,比较,拷贝等操作,并把他们封装成了一个个函数。
2023-07-07 20:37:46
454
3
原创 C++读取一行内个数不定的整数的方式
💯 博客内容:C++读取一行内个数不定的整数的方式😀 作 者:陈大大陈🚀 个人简介:一个正在努力学技术的准前端,专注基础和实战分享 ,欢迎私信!💖 欢迎大家:这里是CSDN,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘 😘 😘。
2023-07-07 16:49:10
1371
35
原创 C++的引用 拷贝赋值和引用赋值
引用是C++里面才有的概念。引用并不是定义了一个新的变量,它只是为一个现存变量起的别名。例如:k就是i的一个别名。定义引用需要注意的地方:来看几个错误的例子巩固一下:但是可以在一条语句中定义多个引用。例如: 拷贝赋值和引用赋值其实就类似于传值和传址的区别。下面来具体看两个代码:运行结果: 运行结果: 第一个是拷贝赋值,第二个是引用赋值。总之一句话,引用即别名。引用并没有创建一个新的变量,只是对原有的变量起了一个新的名字。
2023-07-06 20:12:56
683
4
原创 【PAT B 1010,1011】一元多项式求导 ,A+B和C
设计函数求一元多项式的导数。(注:xn(n为整数)的一阶导数为nxn−1。给定区间 [−231,231] 内的 3 个整数A、B和C,请判断A+B是否大于C。
2023-07-06 16:27:50
600
9
原创 爱玩粥的有福了,带图形界面的明日方舟皮肤的员工管理系统,数据结构期末实训满分。
这个程序底层是easyx图形库,通过在easyx上封装的一个工具类(即输入框、按钮、label等),是在此基础上开发的这个系统。我们期末的数据结构实训已经结束了,我凭借着一手粥批图形界面员工管理系统给老师整不会了,也是顺利得到优秀,接下来就给大家展示一下我一周的成果!
2023-07-03 10:49:42
737
40
原创 【茶话数据结构】查找最短路径——Dijkstra算法详解(保姆式详细图解,步步紧逼,保你学会)
复习到离散数学图论时,想起来这个算法,感觉很有写博客的必要!今天这篇博客就来讲一下查找最短路径的Dijkstra算法。Dijkstra 算法,是由荷兰计算机科学家 Edsger Wybe Dijkstra 在1956年发现的算法,戴克斯特拉算法使用类似广度优先搜索的方法解决赋权图的单源最短路径问题。Dijkstra 算法原始版本仅适用于找到两个顶点之间的最短路径,后来更常见的变体固定了一个顶点作为源结点然后找到该顶点到图中所有其它结点的最短路径,产生一个最短路径树。本算法每次取出未访问结点中距离最小的
2023-06-05 23:50:55
7676
47
原创 【数据结构】插入排序详细图解(一看就懂)
我们将原数组空间看成两个部分,前边是有序部分,后边是无序部分,有序部分我们默认为它就已经是排好序的,在尾部新加入的元素有可能会导致整个有序数组变得无序,因此我们需要进行调整。调整方式就是将新加入的元素进行对比并往前移动,新加入元素和它前边的元素进行对比,如果它比它前边的元素小,则二者互换位置,不断重复这个过程,直到它前边的元素小于它才会停止,这样一来,他就仍然是有序数组。
2023-05-31 11:59:45
2472
57
原创 海量数据中找出前k大数(topk问题),一篇文章教会你
正常思路是把这N个数建成堆,然后 pop k次,即可找到最大的前k个值。但是有些场景,上面的思路解决不了,比如N非常大的情况。假设N是10亿,k是100,就不可能运行出结果。因为如果这样建成堆的话,所占用的空间太大了。10亿个整数需要多大的空间?答案是4GB。4GB的内存啥电脑来了也吃不消,再说100亿,1000亿呢?可见这不是一个可行的方法,咱们另辟蹊径。我们知道,当数据很大时,它不会存在内存上,而是转而储存在磁盘文件里,所以我们的思路就转向磁盘文件。磁盘中能建堆吗?答案是
2023-05-27 23:36:40
2147
47
原创 【数据结构】向上调整建堆和向下调整建堆的天壤之别以及堆排序算法
我们仍旧按最坏的情况来算。最后一层的每个节点都需要向上调整h-1次,光最后一层调整的次数就已经有2^(h-1)*(h-1)次了。光看这一层可以看出差距。上一条讲的向下调整的特点是节点多的层级调整的次数少,是少乘多。而现在讲的向上调整恰恰相反。节点多的层级调整的次数多,是多乘多,这就造成了时间复杂度的巨大差异。同样来计算一下。假设高度为h。F(h)=2^1*1+2^2*2+……+2^(h-2)*h-2+2^(h-1)*(h-1)同样使用错位相减,解得F(h) = 2^h
2023-05-25 20:13:49
1273
36
原创 【重生之我是蜘蛛侠】手把手教你用python爬虫,跟着做就好了
首先要安装bs4这个第三方库。打开pycharm的终端界面,输入pip install bs4即可安装。我之前安装过,所以显示已安装。第三步是导入requests库,没有的话也要安装,步骤和上面的一样,命令变为pip install requests获取豆瓣网页源码先获取网页源码,需要我们先导入requests库。先试试直接获取,看能不能成功。
2023-05-21 22:15:21
1487
50
原创 【LeetCode训练营】用栈来实现队列+用队列来实现栈 详解
每次栈Popst出栈时都要把所有的元素都出完之后,才能从Pushst中追加新数据,当Popst的数据没有全部出栈完成时,不能将Pushst的元素入栈到Popst,这样会导致元素的执行顺序混乱。
2023-05-18 17:02:14
1968
47
原创 假如面试官让你十分钟完成双向循环链表
双向循环链表那么多的功能,怎么是10分钟能写完的东西呢?为了尽可能地减少代码量,让我们能在10分钟内打出来,我们需要发掘其中可以简化的部分。紧接着就是头删和尾删,同理,它们也不过是LTErase函数在头部和尾部的实现而已。要是我问你会不会写双向循环链表,那你一定会不假思索的回答——我当然会。这样的代码量,我勉强能在10分钟之内打完,大家就更不用说了,5分钟足矣。反正头插和尾插也不过是LTInsert函数在头部和尾部的实现而已。如图,我们第一时间想到的恐怕就是这样的写法,又臭又长。实现之后大概就是这个样子。
2023-05-13 18:58:44
1571
41
原创 【闪击Python】字符串的创建和驻留机制
字符串是Python中的基本数据类型,是不可变的字符序列。同样不可变的还有元组。仅保留一份相同且不可变字符串序列的方法,python的驻留机制只对相同的字符串元素保留一次拷贝,之后再创建相同的字符串序列时,不再开辟新的空间,而是把这个字符串的地址赋给新的变量。三个相同字符串的地址是相同的,字符串发生驻留现象。三个变量都储存同一个字符串Python的地址。
2023-05-09 17:51:15
2506
45
原创 【算法竞赛】实现约瑟夫问题的四种方法(附手绘图详解)
动态链表需要临时分配链表节点,使用完毕后需要释放链表节点,动态链表的优点是能及时释放空间,不用使用多余的内存,缺点是需要管理空间,比较容易出错。为了方便大家理解思路,我做出了第一次while循环的图示 ,为了简便,节点就设置成了4个,m的值就设置为3。静态链表较动态链表省去了动态分配和释放储存空间的麻烦。可以加快编码的速度。这是最简单的实现方法。定义一个一维数组,数组的第i个节点的i就是节点的值。
2023-04-26 11:33:42
1798
51
原创 【LeetCode训练营】反转链表 移除链表元素 详细图解 203,206
请你反转链表,并返回反转后的链表。,请你删除链表中所有满足。列表中的节点数目在范围。给你一个链表的头节点。
2023-04-23 23:19:51
2096
51
原创 【LeetCode 训练营 3,5】无重复字符的最长子串+最长回文子串
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。,请你找出其中不含有重复字符的。请注意,你的答案必须是。由英文字母、数字、符号和空格组成。"aba" 同样是符合题意的答案。因为无重复字符的最长子串是。因为无重复字符的最长子串是。因为无重复字符的最长子串是。,所以其长度为 1。,所以其长度为 3。
2023-04-16 15:03:55
2462
50
原创 【LeetCode训练营02】两个非空链表相加 详解
给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0开头。
2023-04-12 23:37:35
1349
15
原创 重生之我是孔乙己——查找数组缺失元素的几种方法
鬼才才能想出来的方法,果然是大道至简!时间复杂度是惊人的o(n),芜湖,最好使竟是最单纯的,感动了!
2023-04-10 07:15:00
1971
15
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人