- 博客(86)
- 收藏
- 关注
原创 C++并发编程-12. 用内存顺序实现内存模型
前文我们介绍了六种内存顺序,以及三种内存模型,本文通过代码示例讲解六种内存顺序使用方法,并实现相应的内存模型。全局一致性模型同步模型(获取和释放)松散模型上面的代码load和store都采用的是memory_order_relaxed。线程t1按次序执行1和2,但是线程t2看到的可能是y为true,x为false。进而导致TestOrderRelaxed触发断言z为0.如果换成memory_order_seq_cst则能保证所有线程看到的执行顺序是一致的。上面的代码x和y采用的是memory_ord
2025-07-10 22:02:09
487
原创 C++并发编程-11. C++ 原子操作和内存模型
本文介绍了3种内存模型,包括全局一致性模型,同步模型以及最宽松的原子模型,以及6种内存序,下一篇将介绍如何利用6中内存序达到三种模型的效果。
2025-07-09 22:24:46
946
原创 C++并发编程-8. 利用并行和函数式编程提升计算效率
这种实现方式比较依赖存储数据的数据结构,比如上面是通过数组存储的,那如果我想实现list容器中元素的排序怎么办?我既不想关注存储的容器,也不想关注存储的类型,想实现一套通用的比较规则?那就需要函数式编程来解决C++函数式编程是一种编程范式,它将计算视为数学上的函数求值,并避免改变状态和使用可变数据。在函数式编程中,程序是由一系列函数组成的,每个函数都接受输入并产生输出,而且没有任何副作用。在C++中,函数式编程可以使用函数指针、函数对象(functor)和lambda表达式等机制来实现。这些机制允许您编写可
2025-07-05 14:50:53
898
原创 C++并发编程-7.C++ 并发三剑客future, promise和async
在这个示例中,std::async 创建了一个新的线程(或从内部线程池中挑选一个线程)并自动与一个 std::promise 对象相关联。std::promise 对象被传递给 fetchDataFromDB 函数,函数的返回值被存储在 std::future 对象中。在主线程中,我们可以使用 std::future::get 方法从 std::future 对象中获取数据。注意,在使用 std::async 的情况下,我们必须使用 std::launch::async 标志来明确表明我们希望函数异步执行。
2025-07-05 08:24:53
752
原创 C++并发编程-6.利用条件变量实现线程安全队列
本文介绍如何使用条件变量控制并发的同步操作,试想有一个线程A一直输出1,另一个线程B一直输出2。我想让两个线程交替输出1,2,1,2…之类的效果,该如何实现?有的同学可能会说不是有互斥量mutex吗?可以用一个全局变量num表示应该哪个线程输出,比如num为1则线程A输出1,num为2则线程B输出2,mutex控制两个线程访问num,如果num和线程不匹配,就让该线程睡一会,这不就实现了吗?比如线程A加锁后发现当前num为2则表示它不能输出1,就解锁,将锁的使用权交给线程A,线程B就sleep一会。Po
2025-06-29 21:06:35
271
原创 C++并发编程-5.C++ 线程安全的单例模式演变
本文介绍C++ 线程安全的单例模式如何实现,通过介绍单例模式的演变历程,给读者更完备的实现单例模式的方案。上述版本的单例模式在C++11 以前存在多线程不安全的情况,编译器可能会初始化多个静态变量。但是C++11推出以后,各厂商优化编译器,能保证线程安全。所以为了保证运行安全请确保使用C++11以上的标准。注意下面的介绍都是C++11标准11以前单例模式的演变历程,C++11以后就直接写成上面哪个就OK,因为C++11要求各厂商必须在多线程的情况下保证静态变量初始化的安全性饿汉式是从使用角度规
2025-06-29 20:01:05
584
原创 C++并发编程-4.unique_lock,共享锁和递归锁
也就是说读操作并不是互斥的,同一时间可以有多个线程同时读,但是写和读是互斥的,写与写是互斥的,简而言之,写操作需要独占锁。如果我们想构造共享锁,可以使用std::shared_lock,如果我们想构造独占锁, 可以使用std::lock_gurad.我们用一个类DNService代表DNS服务,查询操作使用共享锁,而写操作使用独占锁,可以是如下方式的。要想使用共享锁,需使用共享互斥量std::shared_mutex,std::shared_mutex是C++17标准提出的。但是我们可以使用递归锁。
2025-06-27 22:02:09
752
原创 代码随想录-高级篇之动态规划算法
public:// 总体思路:让重量相近的石头先碰撞。// 石头分成两堆:总和一半/2,总和-总和一半的一堆 而且 前一堆>后一堆 向下取整// 最后的结果:/*动规五部曲1. dp[j]的含义重量为j的背包的最大价值为dp[j]2. 递归表达式3. 初始化dp[0] = 0;所有初始化为04. 遍历顺序5. 打印*/++i) // 先遍历物品--j) // 遍历背包,从大往小遍历{ // j >= stones[i] 背包容量不能小于石头的容量。
2025-06-24 18:44:56
682
原创 C++并发编程-2.C++ 线程管控
参考:https://llfc.club/category?catid=225RaiVNI8pFDD5L4m807g7ZwmF#!aid/2Tuk4RfvfBC788LlqnQrWiPiEGW使用起来比较简单,我们直接构造一个joining_thread对象即可。5. 选择运行数量借用C++标准库的std::thread::hardware_concurrency()函数,它的返回值是一个指标,表示程序在各次运行中可真正并发的线程数量.我们可以模拟实现一个并行计算的功能,计算容器内所有
2025-06-17 22:33:56
379
2
原创 11.王道_workflow
/ 计数器//计数器减一// 阻塞主线程,直到按住Ctrl+Cint main()// 等待直到计数器减一freturn 0;
2025-05-15 10:32:40
771
原创 10.王道_HTTP
nlohmann/json是一个header-only的C++ json解析库,可以用于构造和解析JSON对象。键值必须是字符串数据-》字节流:序列化/编码字节流-》数据:反序列化。解码"sites":"site":"name":"王道论坛",},"site":},"site":"name":"微博",
2025-05-08 16:24:59
1024
原创 代码随想录-高级篇之贪心算法
贪心,计算每个站点剩余的,当累加小于0时,以下一站点为起始点开始计算。注意:下标为i的元素的覆盖范围是:i+cover[i]从后往前两个数字两个数字变量遍历。贪的时每次的最大覆盖范围。
2025-04-28 18:20:51
418
原创 8. 王道_网络编程
域名和IP地址的对应关系如何排查网络故障阿强断开重连:客户端终止服务端仍然可以接受新连接accept本质上是一个读操作,读的对象就是分配监听队列中的连接,所以可以使用select监听。这样就可以有新连接到来再做accept操作,这样服务器既可以处理旧连接的收发和新连接的建立当有多个客户端发送消息时,分不清是谁是谁,因为没有像TCP的netfd使用UDP的即时聊天断开连接对方不知道sendto可以发送长度为0的报当主动方要退出时
2025-04-08 14:57:47
756
原创 代码随想录-高级篇之回溯算法
当你举例子,需要不断用到循环时,这时候就要想到回溯,首先应该举例子,画出树形图,递归函数 + for循环回溯方法—纯暴力方法模板。
2025-03-29 17:40:09
407
原创 6.王道_线程
在创建所有线程之后立即销毁了条件变量和互斥量,这是不正确的,因为这些资源在线程运行期间还需要被使用。你应该将pthread_cond_destroy(&share.cond);和pthread_mutex_destroy(&share.mutex);这两行移动到所有线程结束(即调用pthread_join之后)的位置。设置mutex(检错锁和递归锁)的属性来避免第三种死锁类型。只有自己加锁,再加锁才会报错,别人加锁,我再加锁不会报错。作业,A再B之前执行。
2025-03-29 09:35:28
476
原创 5.王道_信号
通常这种状态出现在进程必须不受干扰地等待或者等待事件很快会发生的 时候出现,比如进程正在等待磁盘读写数据的时候。内核不可中断状态是进程等待态的一种形式。mask刚开始为空,当递送信号的过程中会触发一个临时屏蔽,mask会包含这个触犯的信号,当从递送返回的时候mask会删除这个信号。屏蔽的过程中如果产生信号会放入pending中.pending只放一个信号。处于内核不可中断状态(进程控制块的state成员此时为TASK_UNINTERRUPTIBLE)的进程。处于这种的状态的进程在 ps 中显示为。
2025-03-23 10:56:41
258
原创 4.王道_进程间通信
共享内存可以在两个互不关联的进程之间进行通信,只需要彼此之间知道共享内存的键就好了。先后执行shm_w和shm_r程序,后一个进程可以读取共享内存中前一个进程写入的信息。在fork之前打开的文件对象,在fork之后是共享的。只读不写会阻塞,只写不读不会阻塞。
2025-03-22 09:18:42
403
原创 3.王道_进程
粘滞位(Stickybit),或粘着位,是Unix文件系统权限的一个旗标。最常见的用法在目录上设置粘滞位,如此以来,只有目录内文件的所有者或者root才可以删除或移动该文件。如果不为目录设置粘滞位,任何具有该目录写和执行权限的用户都可以删除和移动其中的文件。实际应用中,粘滞位一般用于/tmp目录,以防止普通用户删除或移动其他用户的文件。
2025-03-20 19:18:09
930
原创 2.王道_文件操作
磁盘中的文件设备 — 硬件管道 – 通信简化操作注意在一个返回值是void类型的函数中调用的宏不能有返回值,因为使用宏就是直接替换,有返回值的宏被调用,就相当于无返回值的函数返回值了if!exit1;if==perror;exit1;
2025-03-16 10:45:34
785
原创 代码随想录-基础篇
[left,right] 左闭右闭[left,right)移除元素暴力解法(O(n^2))双指针解法(O(n))思路:在一个数组上定义两个指针,一个是指向“新”数组的指针,一个是指向“旧”数组的指针。有序数组的平方先平方在冒泡排序双指针法首先原数组是递增排列,其中可能具有负数。而平方最大的值只可能出现在左右两边。所以,使用两个指针分别从前和从后向中间扫描,找到最大的值放到新数组的后面(新的数组是从后往前依次存放)长度最小的子数组注
2025-03-09 18:19:57
1088
原创 8. 网络编程
msg.h// 协议头部// 验证码//协议体部//数据}MSG;/** 发送一个基于自定义协议的message,发送的数据存放在buff中* *//*读取一个基于自定义协议的message。读取的数据存放在buff中* */#endifmsg.c// 计算校验码i++)i++)return s;/** 发送一个基于自定义协议的message,发送的数据存放在buff中* */return -1;/*读取一个基于自定义协议的message。
2025-01-29 09:05:36
505
原创 Linux系统程序设计--6.线程
线程基本概念刚创建的进程默认有一个线程,成为主控线程(主线程)Linux线程实现线程标识Linux线程的创建和终止pthread_create龟兔赛跑案例#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<math.h>void * th_fn(void *arg){ int distance = (int)arg; int i ; for
2024-12-26 20:34:14
876
原创 侯捷STL标准库和泛型编程
用于分配管理内存空间allocator的特点是将内存分配(allocate)与对象构造(construct)分离,这样使得对内存的管理更加灵活,性能较高。C++编译器默认已经使用了内置的std::allocator#include //用于标准库中的STL containers它提供一种类型感知的内存分配方法,它分配的内存是原始的、未构造的。GNUG2.9实际上不用上面的用下面的allocG4.9却没用allocTraits 是一种将类型信息与类型本身分离的技术。
2024-12-01 20:39:27
813
原创 Linux系统程序设计--5. 信号
Uninterruptible Sleep(不可中断睡眠,在ps命令中显示“D”)。处在这种状态的进程不接受外来的任何signal,这也是为什么之前我无法用kill杀掉这些处于D状态的进程,无论是“kill”, “kill -9”还是“kill -15”,因为它们压根儿就不受这些信号的支配。D Uninterruptible Sleep.等待磁盘IO。信号0为空信号,一般用来检测特定的进程是否存在。Z Zombie.进程已经结束,仅映像名留存。当无人处理时,子进程就会编程僵尸进程。上述是通过键盘发送信号。
2024-11-27 19:19:24
962
原创 Linux系统程序设计--4.进程
父进程存在,但是子进程终止,其资源没有被系统回收(task_strct)就会称为僵尸进程,但当父进程结束终止时,僵尸进程会被init进程领养称为孤儿进程,然后被init回收。注意:程序中输出的都是虚拟地址。虚拟地址是直接复制过来的,所以地址是相同的。带p的,pathname绝对路径和相对路径均可以,不带p的只能是绝对路径。注意:出来带p的exev函数外,其他的pathname必须带绝对路径。父进程15811先终止,然后子进程15812被init进程领养。判断进程在终止之前是否暂停过。使用kill异常终止。
2024-11-24 16:03:42
1015
原创 gcc和gdb和g++和makefile,CMake
当函数需要返回一个对象的时候,如果自己创建一个临时对象用户返回,那么这个临时对象会消耗一个构造函数(Constructor)的调用、一个复制构造函数的调用(Copy Constructor)以及一个析构函数(Destructor)的调用的代价。而如果稍微做一点优化,就可以将成本降低到一个构造函数的代价,这样就省去了一次拷贝构造函数的调用和依次析构函数的调用。这个选项告诉编译器生成一个包含源文件及其依赖的头文件的列表,而不是编译源文件。注意省略形式的前提时库文件在系统的库文件目录。默认编译选择的是第一个。
2024-11-18 09:23:21
1083
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人