Nginx无锁机制的学习_dong_beijing的博客

nginx无锁机制的学习 最新推荐文章于 2024-03-07 18:25:21 发布 原创 最新推荐文章于 2024-03-07 18:25:21 发布 · 1k 阅读 · 2 · 0 · CC 4.0 BY-SA版权 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 c++ 同时被 2 个专栏收录 106 篇文章 订阅专栏 网络 27 篇文章 订阅专栏 本文探讨了Nginx中CAS操作的应用及其原理,详细介绍了如何利用CAS操作实现进程同步,并对比了CAS操作与互斥锁(mutex)的性能差异。

在nginx中,广泛应用了CAS(compare-and-swap)操作来完成进程同步。

包括ngx_spinlock,ngx_trylock,ngx_rwlock_wlock,ngx_rwlock_rlock,ngx_shmtx_trylock,ngx_shmtx_lock等各种锁,均由ngx_atomic_cmp_set的CAS操作来实现。

CAS操作作为原子操作,在linux上最低的支持版本是GCC4.1,API是

__sync_bool_compare_and_swap(lock, old, set) 在windows上,相应的API是 InterlockedCompareExchange 在C++11中,进行了跨平台的扩展,STL的函数是 atomic_compare_exchange_weak( 在GCC4.1之前的版本,可以用函数来实现CAS操作,在nginx中,给出了实现,也是CAS的原理 static ngx_inline ngx_atomic_uint_t ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, ngx_atomic_uint_t set) { if (*lock == old) { *lock = set; return 1; } return 0; }广泛应用的CAS操作,应该对应于CMPXCHG 汇编指令,是一条原子操作,更确切的实现是这样的: static ngx_inline ngx_atomic_uint_t ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, ngx_atomic_uint_t set) { u_char res; __asm__ volatile ( NGX_SMP_LOCK " cmpxchgq %3, %1; " " sete %0; " : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory"); return res; }

既然nginx中CAS是可以替代各种锁,那用CAS操作当然可以替代最简单的mutex的互斥锁。

替代的方法如下:

int mutex = 0; int lock = 0; int unlock = 1; while (!(__sync_bool_compare_and_swap (&mutex,lock, 1) ))usleep(10000);//100000          //pthread_mutex_lock(&mutex_lock);             count++;                // pthread_mutex_unlock(&mutex_lock);         __sync_bool_compare_and_swap (&mutex, unlock, 0); 用mutex=0表示无线程用count,用mutex=1来表示有人用count。

其中usleep(10000)是我随便写的一个数,来给CPU空闲的事情,在nginx中,用ngx_cpu_pause来给cpu的空闲。

其中ngx_cpu_pause的实现为

__asm__ ("pause") 这里经测试,CAS操作的性能比mutex提升的超过10倍,而cpu的使用率基本一致,这应该是nginx高效的原因。

在nginx中,也并非完全不用mutex,仍然有用ngx_thread_mutex_lock的地方,而ngx_thread_mutex_lock的实现是mutex。

用mutex的原因,在于,需要配合条件变量来一起使用,配合ngx_thread_cond_signal,来完成线程和线程之间的任务分发。

使用mutex获取锁分为两阶段,第一阶段在用户态采用spinlock锁总线的方式获取一次锁,如果成功立即返回;否则进入第二阶段,调用系统的futex锁去sleep,当锁可用后被唤醒,继续竞争锁。这样mutex是有进入内核态,线程进行睡眠。

总结一下,mutex加cond的使用场景,是不常进入,有长期等待的环境,长时间保持锁才需要使用,比如任务的开始或结束。

线程频繁切换的地方,可以完全用CAS操作来进行了,当然采用CAS并不是最优的方法,还需要封装一个spinlock才是正经的道理。

确定要放弃本次机会? 福利倒计时 : :

立减 ¥

普通VIP年卡可用 立即使用 dong_beijing 关注 关注
  • 2 点赞
  • 0 收藏 觉得还不错? 一键收藏
  • 知道了 0 评论
  • 分享 复制链接 分享到 QQ 分享到新浪微博 扫一扫
  • 举报 举报
专栏目录 【Nginx学习】5大绝招揭秘:Nginx进程间通信机制之x86架构下的原子操作 java专栏 12-02 535 原子操作是指不可分割的操作,即在执行过程中不会被中断。在多进程或多线程环境中,原子操作非常重要,因为它可以防止多个进程或线程同时访问同一资源时发生数据竞争和不一致的问题。通过上述的解析,我们可以看到Nginx在x86架构下如何通过CAS、TAS和FAA等指令实现原子操作。从加载旧值、比较和交换到增加和返回,每一步都至关重要。Nginx通过这些步骤,确保了多个工作进程之间的数据同步和一致性,提高了系统的性能和稳定性。希望这次的探索之旅能够让你对Nginx的原子操作机制有了更深的理解。 参与评论 您还未登录,请先 登录 后发表或查看评论 无锁队列实现及使用场景 weixin_46935110的博客 05-11 3102 无锁队列实现及使用场景 无锁队列的实现 | 酷壳 - CoolShell.cn weixin_34292924的博客 01-14 242 无锁队列的实现 | 酷壳 - CoolShell.cn无锁队列的实现 无锁队列实现:Lock free queue 大比拼题目 (tp://coderpk.com/) 05-19 336 04 09/12 Lock free queue 大比拼 10:43 pm by livexmm. Filed under: Code Play,Life 有人在微博上发起了挑战,貌似很碉堡的样子,特别还创建了一个网站: http://coderpk.com/ 一向对解决此类问题有所兴趣于是尝试了我的做法: 首先我想到的问题是我去设计一个纯粹的多读多写无锁队列 【锁】无锁队列、自旋锁队列、互斥锁队列性能对比测试 我的笔记本 09-09 2260 介绍 无锁队列 先大致介绍一下无锁队列。无锁队列的根本是CAS函数——CompareAndSwap,即比较并交换,函数功能可以用C++函数来说明: int compare_and_swap (int* reg, int oldval, int newval) { int old_reg_val = *reg; if (old_reg_val == oldval) *reg = newval; return old_reg_val; } 它将reg的值与oldval的值进行对 nginx的锁 weixin_30394669的博客 01-19 229 一、原理   nginx的锁是基于共享内存实现的,这点跟redis中利用一个存储(也就是一个键值对)来实现锁的原理是一致的,每一项操作通过检查锁对象的lock域是否为0,来判断能否获取锁并尝试获取锁。 二、锁的类定义 1. 类定义 1 //锁的定义 2 typedef struct { 3 #if (NGX_HAVE_ATOMIC_OPS) 4 ngx... 深入理解Nginx的事件处理机制 Nginx事件处理机制概述 ## 1.1 什么是Nginx Nginx(发音"engine-x")是一个轻量级的高性能的HTTP和反向代理服务器,也可以作为邮件(IMAP/POP3)代理服务器。由俄罗斯的程序设计师Igor Sysoev开发,首次公开发布... Java架构师必修课:Nginx企业级教程视频下载 该教程适合具有一定Java基础,并希望深入学习Java后端架构设计和优化,以及Nginx在实际项目中应用的专业人士。内容涵盖但不限于Java高并发架构设计、微服务架构实践、Spring全家桶深度应用、分布式系统构建、Nginx... 基于Nginx内存池实现的VC++内存管理示例 “代码复用”则强调了该项目的工程意义:通过对 Nginx 成熟内存管理机制的学习与移植,开发者能够在自己的项目中快速构建稳定高效的内存管理系统,而不必从零开始设计。这对于构建中间件、网络框架、嵌入式系统等... nginx中锁的设计以及惊群的处理 但行好事 莫问前程 05-03 421 nginx中使用的锁是自己来实现的,这里锁的实现分为两种情况,一种是支持原子操作的情况,也就是由NGX_HAVE_ATOMIC_OPS这个宏来进行控制的,一种是不支持原子操作,这是是使用文件锁来实现。 首先我们要知道在用户空间进程间锁实现的原理,起始原理很简单,就是能弄一个让所有进程共享的东西,比如mmap的内存,比如文件,然后通过这个东西来控制进程的互斥。 说起来锁很简单,就是共享一... 8 nginx锁(spinlock,ngx_shmtx_t) &Ψ的博客 06-23 471 1. 原子变量 1.1 c语言嵌入汇编的写法 asm("汇编语句" :输出寄存器 :输入寄存器 :会被修改的寄存器); 1.2 与原子变量实现相关的汇编指令 1.2.1 lock前缀指令 LOCK指令前缀会设置处理器的LOCK信号,直到使用LOCK前缀的指令执行结束,这会使这条指令的执行变为原子操作。在多处理器环境下,设置LOCK信号能保证某个处理器对共享内存的独占使用。 只能操作下列指令: ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B,CMPXCHG16 文章9:Nginx accept互斥锁 www.keything.net 12-30 8330 欢迎转载,转载请注明出处http://blog.csdn.net/yankai0219/article/details/8453317 文章内容 0.序 1.Nginx锁的核心数据结构 2.分析文件锁 0.序 强烈推荐的文章是nginx中锁的设计以及惊群的处理,本文只是对文章中的内容进行了部分总结和部分解释。 Nginx之所以要采用 kylin实现(1)-----share公共组件(基础组件) weixin_30908103的博客 01-31 296   share中主要包含了kylin中的公共代码组件,例如原子操作,互斥锁,信号量,内存分配器。 1.1 atomic   原子操作主要包含原子add, swap, compAndswap等,在内联汇编中,lock表示执行指令时锁总线(防止在执行该指令时内存被其他CPU的线程修改),memory则表示表示汇编语句可能修改了内存,如果有变量缓存在寄存器中,需要从内存中重新读取该变量 1 ... 详解nginx进程锁的实现 weixin_57218581的博客 06-15 411 nginx是多进程并发模型的应用,但为了网络请求的安全性,必须要使用到锁,那么这个进程锁如何实现呢 一、 nginx进程锁的作用 nginx是多进程并发模型应用,直白点就是:有多个worker都在监听网络请求,谁接收某个请求,那么后续的事务就由它来完成。如果没有锁的存在,那么就是这种场景,当一个请求被系统接入后,所以可以监听该端口的进程,就会同时去处理该事务。当然了,系统会避免这种糟糕事情的发生,但也就出现了所谓的惊群。(不知道说得对不对,大概是那么个意思吧) 所以,为了避免出现同一时刻,有许多进程监听,就 Nginx系列(十一):互斥锁的实现 yang_oh的博客 06-11 703 数据结构 typedef struct { #if (NGX_HAVE_ATOMIC_OPS) ngx_atomic_t *lock; #if (NGX_HAVE_POSIX_SEM) ngx_atomic_t *wait; ngx_uint_t semaphore; sem_t sem; #endif #else ngx_fd... nginx——实现https加密以及重定向 试试看吧。 08-02 4389 一.实现https加密 我们知道现在到了 https 的时代了,每个优秀的网站几乎都已经开启 https。开启了 https 加密访问之后,登录你的网站,浏览器地址栏就会出现一把绿色的锁,这就是使用了超文本传输安全协议(HTTPS),是以安全为目标的HTTP通道,简单来说就是HTTP安全版。 https由两个部分组成:HTTP+SSL/TLS,在http基础上加上了一层加密信息模块,服务端和客户... nginx读写锁的实现逻辑 一个致力于开源代码学习、分析和交流的博客 03-07 511 本文通过源码层面详细分析了nginx的读写锁实现原理。 ngx_shmtx_lock 分析 meetyanfei的博客 05-21 803 作用 在nginx中,此锁用于共享内存分配时上锁,用于进程互斥以及进程内线程互斥。 初始化 ngx_shmtx_create 函数实现 ngx_int_t ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name) { mtx->lock = &addr->lock; if (mtx->spin == (ngx_uint_t) -1) { return NGX_OK 那nginx是不是属于事件驱动IO 最新发布 03-13 <think>好的,用户之前问过Nginx是否采用epoll异步模型,现在接着问Nginx是否属于事件驱动IO。我需要确认用户是否已经了解事件驱动的基本概念,或者是否需要更详细的解释。 首先,用户可能是在学习服务器架构或者网络编程,想理解Nginx的工作原理。他们可能已经知道epoll,但想进一步了解事件驱动的概念。因此,我需要明确事件驱动IO的定义,并将其与Nginx的具体实现结合起来。 接着,我应该回顾之前的回答,确保这次回答连贯。之前提到Nginx使用epoll作为事件驱动模型的一部分,现在需要更深入讨论事件驱动IO的整体结构。需要区分事件驱动和传统多线程模型的区别,突出事件驱动的优势,如高并发、低资源消耗。 然后,我需要检查事件驱动IO的组成部分,比如事件循环、非阻塞IO、多路复用,以及Nginx如何实现这些。可能还要提到主进程和工作进程的分工,以及事件分发的机制。同时,需要澄清事件驱动和异步IO之间的区别,避免用户混淆,因为之前的回答提到epoll属于同步多路复用,但Nginx通过非阻塞模拟异步行为。 还要考虑用户可能的疑问点,例如事件驱动如何处理阻塞操作,或者如何管理大量并发连接。需要强调非阻塞IO的重要性,以及回调函数的作用。此外,可以对比其他服务器模型,如Apache的多线程模型,帮助用户理解不同架构的优缺点。 最后,确保回答结构清晰,分点说明,使用用户易懂的语言,避免过多技术术语,但必要时给出例子或类比。需要验证技术细节的准确性,比如Nginx的事件处理流程、使用的系统调用,以及在不同操作系统上的适配情况。确保所有信息正确无误,并帮助用户建立完整的知识框架。</think>是的,Nginx **完全基于事件驱动 I/O 模型**,这是其高性能的核心设计。以下从原理到实现逐步解释: --- ### 1. **什么是事件驱动 I/O?** 事件驱动 I/O 的核心思想是: **“当某个 I/O 操作(如网络请求、文件读写)的状态发生变化时(例如数据到达或可写入),系统主动通知应用程序,而非应用程序主动轮询”**。 - **关键特征**: - **非阻塞**:应用程序发起 I/O 操作后不阻塞等待,而是继续处理其他任务。 - **异步响应**:当 I/O 就绪时,通过回调函数或事件触发处理逻辑。 --- ### 2. **Nginx 如何实现事件驱动 I/O?** Nginx 的具体实现分为以下层次: #### **① 事件收集层(多路复用器)** - 在 **Linux** 下使用 `epoll`,在 **FreeBSD/macOS** 下使用 `kqueue`,在 **Solaris** 下使用 `event ports`。 - **作用**:通过操作系统接口监听所有连接的 I/O 事件(如可读、可写、错误),并将就绪的事件批量返回。 $$ \text{epoll\_wait()} \rightarrow \text{返回活跃事件列表} $$ #### **② 事件分发层** - **主循环(Event Loop)**:每个 Worker 进程运行一个无限循环,不断调用 `epoll_wait()` 获取就绪事件。 - **事件分派**:根据事件类型(如新连接、数据到达、响应发送)触发对应的回调函数。 #### **③ 非阻塞 I/O 操作** - **Socket 设置为非阻塞模式**:所有连接的读写操作均通过非阻塞方式执行。 ```c // 示例:设置 Socket 为非阻塞 fcntl(fd, F_SETFL, O_NONBLOCK); ``` - **避免阻塞**:若读写时数据未就绪,立即返回 `EAGAIN` 或 `EWOULDBLOCK` 错误,Worker 进程转而处理其他事件。 #### **④ 连接与请求处理** - **单线程处理多连接**:每个 Worker 进程仅用一个线程,但通过事件循环可同时处理成千上万个连接。 - **状态机机制**:HTTP 请求被拆分为多个阶段(如解析头、读取 body、生成响应),每个阶段由事件触发推进。 --- ### 3. **与传统阻塞模型的对比** | **对比项** | **事件驱动模型(Nginx)** | **传统阻塞模型(如 Apache prefork)** | |------------------|----------------------------------|----------------------------------------| | **并发能力** | 单进程数万并发 | 单进程约数百并发(依赖多进程/线程扩展) | | **资源消耗** | 内存占用低,无上下文切换开销 | 高内存消耗(每连接独立进程/线程) | | **适用场景** | 高并发、短连接(如 Web 服务器) | 低并发、长连接(如后台任务) | --- ### 4. **事件驱动模型的限制与应对** - **阻塞操作会破坏模型**: 若在事件回调中执行阻塞操作(如同步磁盘 I/O、复杂计算),整个 Worker 进程会被阻塞。 **Nginx 的解决方式**: - 异步文件 I/O(通过线程池或 `AIO` 系统调用)。 - 将耗时任务拆分为非阻塞步骤。 --- ### 5. **总结:Nginx 的事件驱动本质** - **事件驱动是架构基础**:Nginx 从连接管理到请求处理完全依赖事件触发,而非线程/进程调度。 - **高性能的关键**: - 通过 `epoll`/`kqueue` 最大化减少无效轮询。 - 非阻塞 I/O 保证 CPU 始终处理有效任务。 - 无锁设计避免多线程竞争。 因此,Nginx 是**典型的事件驱动 I/O 模型**,而非基于线程池或进程池的同步阻塞模型。 dong_beijing

博客等级

码龄9年 185 原创 212 点赞 739 收藏 135 粉丝 关注 私信

热门文章

  • c++的sort函数用lamda表达式自定义排序 39941
  • 通过openssl生成sm2的公私钥的方法 37669
  • linux的c/c++的运行报错“terminate called after throwing an instance of 'std::system_error'”的处理 36780
  • linux遇到非法指令( Illegal instruction)的处理方法 34039
  • ubuntu弹出磁盘空间不足的解决方法 25796

分类专栏

  • 数据安全 2篇
  • windows 5篇
  • 网络 27篇
  • ffmpeg 8篇
  • ti 1篇
  • ubuntu 21篇
  • android 5篇
  • boost 5篇
  • c++ 106篇
  • Java
  • go 14篇

展开全部 收起

上一篇: nginx的守护进程学习 下一篇: nginx的spinlock的学习

最新评论

  • GO语言工程构建示例-mac和linux适用

    CSDN-Ada助手: 不知道 CS入门 技能树是否可以帮到你:https://edu.csdn.net/skill/gml?utm_source=AI_act_gml

最新文章

  • GO语言工程构建示例-mac和linux适用
  • linux服务器网络常见工具入门
  • SystemTap (stap) 工具入门
2024年5篇 2023年7篇 2022年1篇 2021年2篇 2020年11篇 2019年38篇 2018年74篇 2017年48篇

目录

展开全部

收起

目录

展开全部

收起

上一篇: nginx的守护进程学习 下一篇: nginx的spinlock的学习

分类专栏

  • 数据安全 2篇
  • windows 5篇
  • 网络 27篇
  • ffmpeg 8篇
  • ti 1篇
  • ubuntu 21篇
  • android 5篇
  • boost 5篇
  • c++ 106篇
  • Java
  • go 14篇

展开全部 收起

目录

评论 被折叠的 条评论 为什么被折叠? 到【灌水乐园】发言 查看更多评论 添加红包 祝福语

请填写红包祝福语或标题

红包数量

红包个数最小为10个

红包总金额

红包金额最低5元

余额支付 当前余额3.43元 前往充值 > 需支付:10.00元 取消 确定 下一步 知道了 实付 使用余额支付 点击重新获取 扫码支付 钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

Từ khóa » Ngx Rwlock.c