无锁技术
自旋锁
自旋锁是最基本的一种无锁技术,采用基于 CAS(Compare-and-Swap)的操作,尝试获取锁,失败时采用轮询的方式等待资源,避免线程被阻塞,不需要系统调用,从而减少上下文切换和性能损耗。
原子操作使用 CPU 提供的原子性指令,属于硬件层面的,实现数据的原子性访问和修改,避免使用锁导致的线程阻塞和竞争,同时也避免了死锁的发生。
加锁区执行速度快的情况下可以使用该锁。
atomic提供的常见方法:
- store:原子写操作。
- load:原子读操作。
- compare_exchange_strong:传入[期望原值]和[设定值],当前值与期望值相等时,修改当前值为设定值,返回true;当前值与期望值不等时,将期望值修改为当前值,返回false。
- compare_exchange_weak:同上,但允许偶然出乎意料的返回(比如在字段值和期待值一样的时候却返回了false),比strong性能更好些,但需要循环来保证逻辑的正确性。
- exchange:交换2个数值,并保证整个过程是原子的。
C++11标准中提供了 std::atomic 模板类,用于实现原子操作,可用于实现 CAS 操作,从而实现无锁编程。
在非并发条件下,实现一个栈的Push操作,通常有如下操作:
- 步骤1:新建一个节点,node* const new_node = new node(data);
- 步骤2:将该节点的next指针指向现有栈顶,new_node->next = head;
- 步骤3:更新栈顶,head = new_node
常用设计模式
系统梳理软件开发中常用的设计模式,深入解析策略模式、观察者模式、责任链模式等核心模式的实现原理与应用场景,提供完整的C++代码示例,帮助开发者掌握设计模式在实际项目中的灵活运用。
leetcode-双指针相关题型
双指针相关题型
leetcode: 几个数之和系列
几个数之和系列
公众号留言功能开通方法(2020版)
公众号留言功能怎么开通?(2020)
网上已经有各种资料已经说的很清楚了,18年3月后就关闭了留言功能,政策原因,理解一下。
企业类型公众号的可以考虑通过公众号迁移来开通留言功能,简单来说就是将别人订阅号的留言功能迁移到你的企业类型订阅号上,这样你的号就有留言功能了,迁移的目标账户必须是组织类型的账户如企业类型订阅号。迁移的具体流程为:)
那么到底什么是公众号迁移?
因为公众号不支持直接变更主体,所以公众平台推出帐号迁移功能,通过此功能可将A帐号的粉丝、违规记录、文章素材(可选)、微信号(可选)迁移至B帐号。
温馨提示:例如帐号A迁移至B,那迁移完成,A帐号被回收,B帐号获得A帐号的粉丝等信息继续使用,但主体还是B。
libevent回调函数分析——evhttp_connection_cb容易出现的bug
在这个函数中,会调用getsockopt函数,获取socket套接字是否有连接的异常,但是这个getsockopt函数有个连续调用的问题,如果你第二次调用这个函数,之前fd上的错误就被清除了,导致本来这个socket套接字是有问题的,但是检测不出来了,目前这个evhttp_connection_cb的bug就在这里,如果后端服务器根本就没有开启的情况下,该函数中的getsockopt也检测不到异常了,导致其误以为连接上了,流程会一直往下走,会继续去读取后端服务器的body,却发现读不到数据,导致连接503错误,原本应该是getsockopt检测到连接异常后,就响应500的错误的。
C++实现简单的HTTP Server
可以参考下典型的http会话,服务器响应由一系列文本指令组成, 并使用 CRLF 分隔,它们被划分为三个不同的块:
- 第一行是 状态行,包括使用的HTTP协议版本,状态码和一个状态描述(可读描述文本)。
- 接下来每一行都表示一个HTTP首部,为客户端提供关于所发送数据的一些信息(如类型,数据大小,使用的压缩算法,缓存指示)。与客户端请求的头部块类似,这些HTTP首部组成一个块,并以一个空行结束。
- 最后一块是数据块,包含了响应的数据(如果有的话)。
具体实现如下代码,收到postman发过来的消息后,将收到的消息显示出来,并回复状态ok的响应,这就完成了一个最简单的http服务器模型。
1 | #include <iostream> |
这里写法可以留意一下,将socket建立,绑定监听放在while循环之上,循环里面只要连续的accept就行了,完了之后把accept的fd给close掉,close就是代表主动关闭连接了。
如果你没有下载postman的话,也可以使用curl命令发送请求。
TCP服务器C语言实现
参考链接:https://www.geeksforgeeks.org/tcp-server-client-implementation-in-c/
建立HTTP服务器的流程都是一样的,可以参考TCP Server的建立过程,因为Http是基于Tcp协议的,底层的原理都是相通的,参考了man手册大概介绍一下。
创建socket
创建socket,此时会返回一个描述符,头文件为#include <sys/socket.h>,函数原型为int socket(int domain, int type, int protocol);,domain参数指明通信将在哪个通信族发生,一般选PF_INET即Iternet版本4协议,socket参数指明通信的类型,可选择SOCK_STREAM/SOCK_DGRAM/SOCK_RAW,SOCK_STREAM类型提供基于序列的,可靠的,双向连接的字节流,可以支持带外数据传输机制,指的是TCP。 SOCK_DGRAM套接字支持数据报(无连接,不可靠的最大固定长度(通常很小)的消息),指的是UDP。 SOCK_RAW套接字提供对内部网络协议和接口的访问,仅超级用户可用。protocal协议指明与套接字使用的特定的协议,一般填0即可。
SOCK_STREAM类型的套接字是全双工字节流,类似于管道。 流套接字必须处于连接状态,然后才能在其上发送或接收任何数据。 通过connect或connectx调用创建与另一个套接字的连接。 连接后,可以使用read和write调用或send和recv调用的某些变型函数传输数据。 当会话已完成时,可以执行close。 带外数据也可以按照send中的说明进行发送,也可以按照recv中的说明进行接收。
如果发生错误,则返回-1,否则返回值是引用套接字的描述符。
所以可以这么写:
1 | // socket create and verification |