自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(61)
  • 收藏
  • 关注

原创 【线程】自旋锁和读写锁

以前所讲的是挂起等待锁,申请锁成功继续执行,申请失败挂起等待挂起等待和唤醒是需要时间的,有没有一种锁不会挂起等待呢?那就是自旋锁,申请锁失败它不会挂起,他会轮询,一直让我们的线程申请锁以前用的接口lock就是挂起等待的,而trylock是会立即返回,不会挂起等待,用trylock的时候我们可以用循环来让他轮询一直让我们的线程申请锁然后pthread库也提供了另一种锁的接口是不是发现它也有trylock的版本,是不是有疑问了?

2024-09-25 20:38:23 346

原创 【线程】线程安全的单例模式

IT行业这么火, 涌入的人很多. 俗话说林子大了啥鸟都有. 大佬和菜鸡们两极分化的越来越严重. 为了让菜鸡们不太拖大佬的后腿, 于是大佬们针对一些经典的常见的场景, 给定了一些对应的解决方案, 这个就是设计模式。下面把这一篇文章的线程池改为懒汉模式的单例,改动了构造和析构函数,防止构造出第二个对象,多了一个静态的类的指针成员,来获取这个类。第一次调用 GetInstance 的时候, 如果两个线程同时调用, 可能会创建出两份 T 对象的实例.单例模式是一种 "经典的, 常用的, 常考的" 设计模式.

2024-09-25 19:40:58 337

原创 【线程】线程的封装

C++提供有线程库,他的底层其实也是用原生线程库封装的。下面直接看看C++提供的线程库的基本使用。下面直接进行封装,看看是怎么封装的。

2024-09-25 17:44:03 150

原创 【线程】线程池

线程池是创建出一堆线程,类似于池,创建出线程池,提前创建出一批线程,当有任务的时候,就可以直接交给线程池处理,这样可以很好的提高效率。池化技术,弄一个池,预先弄好资源,当有比如任务来的时候,就交给这个池,就可以很快的处理任务。大家可以拷贝到VS Code下来看。下面利用原生线程库来实现线程池。

2024-09-25 16:57:27 135

原创 【线程】POSIX信号量---基于环形队列的生产消费者模型

POSIX信号量和SystemV信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的。 但POSIX可以用于线程间同步

2024-09-25 15:21:06 772

原创 【线程】线程的同步---生产消费者模型

理解条件变量和生产者消费者模型

2024-09-22 18:51:58 1018

原创 【线程】线程的互斥---互斥锁

多线程执行流共享的资源就叫做临界资源:每个线程内部,访问临界资源的代码,就叫做临界区:任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用:不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么未完成,没有正在做的概念。

2024-09-20 16:33:56 666

原创 【线程】线程的控制

线程的控制:线程的创建,线程的终止,线程的等待,线程的分离,创建多线程

2024-09-18 10:10:03 1203

原创 【线程】线程的概念

计算的是在物理内存的偏移量。用10位比特位说明项目录二级页表表项有1024个,用12位是刚刚好符合物理内存划分为很多个块,每个块是4KB,这样算出的偏移量就不会超过这个大小。其实每个页表里还会有一部分来说明权限其他问题的,我们不说一个进程是不会把进程空间全部用完的,也就是说项目录里的表项没有全部填满,对应的二级页表也就没有1024个,这样页表用的空间就没有那么大int a =10;

2024-09-15 11:18:48 871

原创 【信号】SIGCHLD信号--了解

事实上,由于UNIX 的历史原因,要想不产生僵尸进程还有另外一种办法:父进程调用sigaction(也可以用signal)将SIGCHLD的处理动作置为SIG_IGN,这样fork出来的子进程在终止时会自动清理掉,不会产生僵尸进程,也不会通知父进程。系统默认17号信号的处理动作是忽略动作和用户用sigaction函数自定义的忽略 通常是没有区别的,但这是一个特例。,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在。

2024-09-13 16:05:09 282

原创 volatile关键字

当进行循环判断以及逻辑反运算时,都需要运算器计算,要被加载到CPU中,优化导致flag变量优化到了CPU的寄存器中,因为优化导致内存不可见,CPU不会从内存读数据,你修改的flag为1,在内存里修改的,对于CPU是不可见的,CPU就认识寄存器中flag,所以就一直死循环。有些编译器在release下,是会对代码自动优化的,而g++编译器是不会自动优化,要带选项。在优化条件下, flag变量可能被直接优化到CPU内的寄存器中。往下翻,-O选项,编译器优化选项,数字代表优化级别。发现进程不会退出了,为什么呢?

2024-09-13 15:11:54 231

原创 可重入函数

main函数调用insert函数向一个链表head中插入节点node1,插入操作分为两步,刚做完第一步的 时候,因为硬件中断使进程切换到内核,再次回用户态之前检查到有信号待处理,于是切换到sighandler函数,sighandler也调用insert函数向同一个链表head中插入节点node2,插入操作的两步都做完之后从sighandler返回内核态,再次回到用户态就从main函数调用的insert函数中继续 往下执行,先前做第一步之后被打断,现在继续做完第二步。2.调用了标准I/O库函数。

2024-09-13 11:38:47 217

原创 ​​【信号】信号的处理

在信号递达时就调用这个函数,这称为。

2024-09-13 11:17:24 1170

原创 【信号】信号的保存

实际执行信号的处理动作称为信号从产生到递达之间的状态,称为。进程可以选择(Block )某个信号。被阻塞的信号产生时将保持在,直到进程对此信号的阻塞,才执行递达的动作.,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。进程在接收到信号之后,可能不处理,那么信号就会保存,等到合适的时候再进行处理,一般这个信号会保存在一张位图里,这个,比特位的0和1代表信号比特位的位置代表,所谓保存信号就是修改这张位图的内容,OS是进程的管理者,它才有资格修改这张位图的内容。

2024-09-12 19:53:07 934

原创 【信号】信号的产生

就是数组,内容是某个中断号对应方法的地址,CPU拿到中断号,就找到对应的方法,OS就会知道,OS就会实现对应的方法,假如是读取键盘的方法,那么OS就会从键盘读取数据到键盘缓冲区里。我们生活中的红绿灯,闹钟,外面电话等等这些都是信号,我们是怎么认识这些信号的,我们认识这些信号,并且知道这些信号的处理方法,对于进程来说,也会认识相应的信号。给进程设置一个闹钟,时间一到闹钟就响,就会向进程发送14号信号,进程退出,返回值是闹钟的剩余时间,可以不用管。,信号本来是有默认动作的,用了这个函数可以自定义信号的动作。

2024-09-08 20:49:57 925

原创 【进程间通信】System V--消息队列和信号量

里的队列就是数据结构里的队列,A进程通过数据块的形式发送给B进程,B进程也可以通过数据块的形式发送给A进程,这些数据块就在内存中以队列的形式来组织,A,B进程怎么知道哪个是自己的数据块呢?申请资源,本质是对cnt--,P操作,释放资源,本质是cnt++,V操作,申请和释放的PV操作是原子的,原子意思就是要么不做,做就做完,没有正在做的状态,这样的原子性就不会导致上面的问题。当一个执行流申请一个共享资源时,这个计数器就减减,当计数器减到0时,执行流就申请失败临界资源了,计数器资源就是计数器里的资源。

2024-09-08 11:48:41 423

原创 【进程间通信】共享内存

共享内存是内存的一部分,进程间通过共享内存通信首先申请共享内存,然后再把共享内存挂接到自己的进程地址空间(虚拟地址)的共享区,返回首地址。

2024-09-04 17:41:20 203

原创 简易日志类制作

当我们写代码的时候,需要打印日志的,就需要一个简易日志类来实现。vsnprintf的使用比较复杂,就按照代码那里那样写吧。第一个函数:打印信息函数 ,利用可变参数列表。日志包括:日志时间,日志等级,日志内容等等。怎么在代码中获取时间呢?warning:报警信息。error:错误信息。fatal:致命信息。debug:调试信息。

2024-09-04 15:28:28 160

原创 【进程间通信】命名管道

匿名管道是具有血缘关系的进程才能使用,如果是没有任何关系的进程,就用进行通信。命名管道是具有名字的管道文件,也是一种内存级文件,不用刷新到磁盘问题:如果两个不同的进程打开同一个文件,在内核里,操作系统会打开多少个文件呢?1个那么这两个进程怎么知道是同一个文件呢?通过同一路径下的同一个文件=路径+文件名(具有 唯一性)命名管道的原理和匿名管道一样的,打开同一个文件,一个读,一个写。

2024-09-04 10:57:51 340

原创 【进程间通信】管道应用场景---简易进程池

【代码】【进程间通信】管道应用场景---简易进程池。

2024-09-01 20:47:20 243

原创 【进程间通信】匿名管道

管道的四种情况可以写代码自己看看。

2024-09-01 17:36:15 286

原创 动静态库的制作和使用

静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

2024-08-29 15:31:50 340

原创 软硬链接

上面我们发现,建立的软链接文件的inode编号和指向文件不同,而建立的硬链接文件inode编号没变,为什么呢?ln -s 指向的文件 软连接文件。ln 原来文件 硬连接文件。为什么不能给目录创建硬链接?

2024-08-27 16:32:36 120

原创 【基础IO】文件系统

当我们存入数据时,就是在磁盘的盘面上写0 1的二进制序列来保存信息。这样子就可以知道文件在磁盘的什么位置,怎么找到的了。磁盘是唯一的机械设备,属于外设。

2024-08-27 15:35:15 132

原创 【基础IO】用户级缓冲区

到了fork之后,创建子进程,本来数据是父子进程共享的,但是程序退出,要把缓冲区的内容刷新出去,发生。,这样就生成了两份,write是系统接口,不会进入缓冲区,也就不会有两份。在FILE这个结构体中除了有文件描述符,还定义有缓冲区。当我们重定向到文件里面,刷新策略就变成了。简单模拟实现一个缓冲区的代码,供我们理解。这个缓冲区在哪里呢?

2024-08-24 10:13:53 205

原创 【基础IO】文件重定向的原理

总的来说,stdout是打印常规信息,stderr是打印错误信息,都是向显示器打印,只是信息不同,和文件描述符不同。我们发现,本来应该输出到显示器上的内容,输出到了文件 myfile 当中,其中,fd=1。假如我们要把常规信息放在一个文件,错误信息放一个文件,怎么做?当你把1号关闭,那么新打开的文件的描述符是1了,而不是3了。它们都是显示器文件,一个是1号,一个是2号,有什么区别呢?stdout是标准输出,stderr是标准错误。运行一下,发现没在屏幕上,在文件中。可以利用dup2来完成重定向。

2024-08-23 20:12:41 339

原创 【进程】进程的替换

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以。进程替换不仅可以替换为系统程序,还可以替换自己写的程序,也就是说C++的程序经过替换可以替换成其他语音的程序。e可以理解为环境的意思,就是说这个函数可以传递环境变量。p代表path,就是已经知道环境变量了,会自动搜索路径。,从新程序的启动例程开始执行。当进程调用一种exec函数时,该进程的。l可以理解为list,表示参数使用列表。,所以调用exec前后该进程的id并。exec系列函数有6个。

2024-08-22 09:57:22 195

原创 可变参数模版

名字可以自由取上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的,只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特点,也是最大的难点,即如何展开可变模版参数。

2024-06-06 16:17:09 270

原创 左值引用和右值引用

1. 左值引用只能引用左值,不能引用右值。2. 但是const左值引用既可引用左值,也可引用右值。

2024-06-06 15:59:43 884

原创 C++异常处理

我们知道抛出异常的类型是任意类型,一般我们都会用自定义类型实际使用中很多公司都会自定义自己的异常体系进行规范的异常管理,因为一个项目中如果大家随意抛异常,那么外层的调用者基本就没办法玩了,所以实际中都会定义一套继承的规范体系。这样大家抛出的都是继承的派生类对象,捕获一个基类就可以了class Exception//基类public:, _id(id){}protected:int _id;class SqlException : public Exception//派生类。

2024-05-30 20:00:55 643

原创 位图和布隆过滤器

给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中?可以用set或unordered_set吗?我们知道1G大概10亿字节,40亿个整数需要160亿字节,也就是16G,还没有加上其他的东西也要开空间,所以已经超过了内存的大小,就无法无法全部加载到内存。你们是不是想说我一部分一部分加载到内存就可以了,也是不好,太慢了有什么好的解决方案吗?我们可以用位图,位图就是用去这个数在不在,在就是1,不在就是0。用直接定值法去映射。

2024-05-24 15:48:02 838

原创 哈希表----开散列

/记录表中数据个数。

2024-05-20 09:54:17 235

原创 哈希表----闭散列

当我们用哈希函数的时候,其中一个就是取这个表的长度len,按照哈希函数:Hash(key) = key% len,将这个位置映射到表中通过上面的除留余数法,会有的问题,可以通过来解决也叫,通过线性探测,依次找后面的位置存储。

2024-05-19 21:41:16 513

原创 红黑树的平衡

/库里面提供的结构体,表示key和value颜色初始化必须是红色,如果插入的是黑色,必定会影响每条路径的黑色节点的数量,红色的话只会影响该条路径。

2024-05-15 00:06:00 259

原创 AVL树的旋转

每个节点子树高度差的绝对值不超过1(注意节点中如果没有平衡因子),节点的平衡因子是否计算正确。(或者反过来,我们用前面那种)平衡因子=[-1,1],当超出这个范围,搜索树就不平衡了。就是每个节点的左右子树的高度差不超过1,称平衡的搜索树为。是不是感觉这样就链接上了,其实不对的,每个节点的父亲也要更新的。和左单旋是类似的,读者可以模仿上面来分析,自己把它写出来。我们知道搜索二叉树有缺陷,就是不平衡,比如下面的树。更新节点指向是一定要更新他的父亲节点的指向。, 那我们怎么控制搜索树的平衡呢?

2024-05-11 08:47:51 424

原创 二叉搜索树的插入和删除

当root是空的时候怎么处理的?为什么用个引用就解决了呢?间接删除:找它的左子树的最大节点代替,也就是左子树的最右节点 或。上面情况可以解决,但是有些情况不能解决,比如。找它的右子树的最小节点代替,也就是右子树的最左节点。你以为第一种情况就解决了吗?如果是下面的情况呢?若它的左子树不为空,则左子树上所有节点的值。若它的右子树不为空,则右子树上所有节点的值。它的左右子树也分别为二叉搜索树。这个很简单,直接给你们看了。是不是发现崩了,为什么呢?

2024-05-03 20:23:44 391

原创 多态的原理

多态就是硬套条件,符合多态就按多态走,不符号多态就按类型走// 这里常考一道笔试题:sizeof(Base)是多少?return 0;运行发现Base的大小是8字节,为什么呢?通过调试我们发现,Base对象除了有_b成员变量,还存在一个_vfptr变量, 这个变量是虚函数表指针简称虚表指针。虚函数表简称虚表:存着虚函数地址的函数指针数组,一个含有虚函数的类至少有一个虚表。

2024-05-03 10:20:28 666

原创 多继承及菱形继承

可以通过。

2024-05-02 19:59:02 896

原创 main函数的三个参数

main函数有三个参数

2024-04-04 20:12:51 232

原创 【进程】进程的状态

一个进程退出,但是它的资源还不允许被操作系统释放,处于被检测状态 ,只能由操作系统和父进程释放,所以如果一直不释放会导致内存泄漏,可以用进程等待来进行处理。父进程先退出,子进程后退出,子进程进入Z态,这个子进程就成了孤儿进程,他会被1号init进程领养,也由它回收。当对磁盘进行写入时,突然中断,这时磁盘就在一直等待写入,一直等,这个也叫不可中断睡眠,要自己慢慢等待结束。例如:子进程先退出,父进程还没退出,子进程就进入僵尸状态,父进程可以通过等待来处理子进程。PCB结构体在等待队列中,等待非CPU资源就续。

2024-04-04 19:36:52 291

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除