自旋锁简介
Nginx框架使用了三种消息传递方式:共享内存、套接字、信号。
Nginx主要使用了三种同步方式:原子操作、信号量、文件锁。
基于原子操作,nginx实现了一个自旋锁。自旋锁是一种非睡眠锁。如果某进程视图获得自旋锁,当发现锁已经被其他进程获得时,那么不会使得当前进程进入睡眠状态,而是始终保持进程在可执行状态,每当内核调度到这个进程执行时就持续检查是否可以获取到所锁。
自旋锁的应用场景
自旋锁主要是为多处理器操作系统而设置的,他要解决的共享资源保护场景就是进程使用锁的时间非常短(如果锁的使用时间很久,自旋锁不合适,因为会占用大量的CPU资源)。
大部分情况下Nginx的worker进程最好都不要进入睡眠状态,因为它非常繁忙,在这个进程的epoll上可能有十万甚至百万的TCP连接等待着处理,进程一旦睡眠后必须等待其他事件的唤醒,这中间及其频繁的进程间切换带来的负载消耗可能无法让用户接受。
自旋锁源码分析
下面通过源代码看自旋锁的具体实现(Nginx_spinlock.c,Nginx1.4.1版本):
/** Copyright (C) Igor Sysoev* Copyright (C) Nginx, Inc.*/#include <ngx_config.h>
#include <ngx_core.h>//函数:基于原子操作的自旋锁方法ngx_spinlock的实现
//参数解释:
//lock:原子变量表达的锁
//value:标志位,锁是否被某一进程占用
//spin:在多处理器系统内,当ngx_spinlock方法没有拿到锁时,当前进程在内核的一次调度中该方法等待其他处理器释放锁的时间
void
ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin)
{#if (NGX_HAVE_ATOMIC_OPS)//支持原子操作ngx_uint_t  i, n;//一直处于循环中,直到获取到锁for ( ;; ) {//lock为0表示没有其他进程持有锁,这时将lock值设置为value参数表示当前进程持有了锁if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) {return;}//如果是多处理器系统if (ngx_ncpu > 1) {for (n = 1; n < spin; n <<= 1) {//随着等待的次数越来越多,实际去检查锁的间隔时间越来越大for (i = 0; i < n; i++) {ngx_cpu_pause();//告诉CPU现在处于自旋锁等待状态}//检查锁是否被释放if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) {return;}}}//当前进程让出处理器,但仍然处于可执行状态ngx_sched_yield();}#else#if (NGX_THREADS)#error ngx_spinlock() or ngx_atomic_cmp_set() are not defined !#endif#endif}
上面的代码需要注意的是:在多处理器下,当发现锁被其他进程占用时,当前进程并不是立刻让出正在使用的CPU处理器,而是等待一段时间,看看其他处理器上的进程是否会释放锁,这会减少进程间切换的次数。
函数ngx_cpu_pause():是虚度哦架构体系中专门为了自旋锁而提供的指令,它会告诉CPU现在处于自旋锁等待状态,通常一个CPU会将自己置于节能状态,降低功耗。但是当前进程并没有让出正在使用的处理器。
函数 ngx_sched_yield():当前进程仍仍然处于可执行状态,但暂时让出处理器,使得处理器优先调度其他可执行状态的进程,这样,在进程被内核再次调度时,在for循环代码中可以期望其他进程释放锁。

Nginx学习之四-Nginx进程同步方式-自旋锁(spinlock)相关推荐

  1. 【005】Nginx学习笔记-Nginx真实IP

    [005]Nginx学习笔记-Nginx真实IP 真实IP 客户端真实IP 深入理解真实IP 实验一 实验二: 多个代理服务器的情况 实验三:利用realip模块获取客户端真实IP 实验四:伪装请求头 ...

  2. Nginx学习(一)——Nginx基础知识

    目录 1.Nginx学习(一)--Nginx基础知识 2.Nginx学习(二)--配置文件.反向代理与负载均衡 3.Nginx搭建HTTPS服务器 一.初试Nginx 一.下载安装 1.安装必要的一些 ...

  3. 自旋锁SpinLock小案例

    自旋锁(spinlock) 是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU

  4. Nginx学习之Nginx高性能的实现原理

    Nginx 采用的是多进程(单线程) & 多路IO复用模型,使用了 I/O 多路复用技术的 Nginx,就成了"并发事件驱动"的服务器,同时使用sendfile等技术,最终 ...

  5. Nginx学习之Nginx进程

    Nginx学习 Nginx命令 ./nginx:启动Nginx: ./nginx -s stop:关闭Nginx,立即关闭,不管有没有已接受的请求: ./nginx -s reload:重新加载ngi ...

  6. 【Nginx学习】Nginx代理mysql数据库

    文章目录 一.使用docker安装Nginx 1.安装Nginx 2 .启动容器 二.命令查看端口 1.查看Liunx端口占用 2.命令nmap端口扫描 3.docker容器的本机ip地址 三.doc ...

  7. 自己动手实现自旋锁(spinlock)

    大多数的并行程序都需要在底层使用锁机制进行同步,简单来讲,锁无非是一套简单的原语,它们保证程序(或进程)对某一资源的互斥访问来维持数据的一致性,如果没有锁机制作为保证,多个线程可能同时访问某一资源,假 ...

  8. C#线程锁(自旋锁SpinLock、互斥锁Mutex、混合锁Monitor | lock)

    一.自旋锁 自旋锁是指当一个线程在获取锁对象的时候,如果锁已经被其它线程获取,那么这个线程将会循环等待,不断的去获取锁,直到获取到了锁.适合于原子操作时间非常短的场景 优点:避免了线程上下文切换.性能 ...

  9. 自旋锁spinlock解析

    1 基础概念 自旋锁与相互排斥锁有点类似,仅仅是自旋锁不会引起调用者睡眠.假设自旋锁已经被别的运行单元保持.调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁."自旋"一词就 ...

最新文章

  1. HDU4587(割点+最大连通分量)
  2. SqlBulkCopy与触发器,批量插入表(存在则更新,不存在则插入)
  3. DataGridView数据验证CellValidating()
  4. 【转】Android子线程真的不能更新UI么
  5. wordpress PHP合并js,如何在WordPress中添加外部JavaScript
  6. shiro 字段不是username 和password_Shiro整合JWT
  7. 20172311 2017-2018-2 《程序设计与数据结构》第八周学习总结
  8. 《走遍中国》珍藏版(十)
  9. 利用最新Apache解析漏洞(CVE-2017-15715)绕过上传黑名单
  10. Ajax(二)-XMLHttpRequest(核心)对象的属性和方法
  11. 数据链路层的流量控制
  12. BZOJ3108 [cqoi2013]图的逆变换
  13. gitlab . pre-receive hook declined
  14. CSS固定定位 将模块固定到版心右边
  15. 1965:【14NOIP普及组】珠心算测验
  16. Mysql为什么使用B+树(一)之红黑树简述
  17. 海关数据有用吗?看看资深外贸怎么说!
  18. Android客户端Push 透传与通知栏
  19. 如何利用业余时间快乐的赚钱
  20. KVM虚机转换为VMware虚机

热门文章

  1. RepPoints(本质是可变形卷积DCN)再理解
  2. conda创建虚拟环境,拥有多个Anconda版本
  3. 0x00000116
  4. mysql 函数用还是不用_Mysql中日期和时间函数应用不用求人
  5. 成功安装mysql后,为何服务管理器里找不到MySQL服务名(解析篇)
  6. 趣味娱乐小程序源码多流量主 趣味制作/藏头诗/隐藏图
  7. mysql geocode_百度地图Geocoding API获取特定地区或地址的经纬度信息,然后在MySql数据库多表循环遍历更新...
  8. wordpress常用插件打包 百度搜索推送插件+sitemap生成等
  9. springmvc接收日期字段处理方式
  10. 小程序博客资源娱乐网带微信流量主激励视频