nginx源码分析1———进程间的通信机制二(自旋锁)
2015-07-23 18:53
811 查看
自旋锁的相关介绍
自旋锁的释义自旋锁与其他的锁最大的区别就是自旋锁不会引起调用者睡眠(非睡眠锁),也就是始终是可执行状态。如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里,看是否该自旋锁的保持者已经释放了锁。
自旋锁的适用场景
当锁的使用时间很短的时候,就可以采用自旋锁,这样开销很小。如果时间很长,锁一直自旋,又不能调度其他的程序,cpu资源将被大量占用,这样就不是很合适。对于长时间的锁,应该使用让它休眠的锁,而不应该是自旋。
自旋锁无论是单核还是多核,都将是有效的,一直处于可执行态,是可以少一些状态的转换,如果切换到睡眠态,还得从休眠态转化到就绪态,然后才能供cpu调度(如果不是很清楚,就得多了解操作系统处理器调度相关的知识)。
nginx的相关实现
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 ( ;; ) { //先判断一次锁,然后尝试获取锁(compare and set) if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) { //如果成功获取到就直接return。 return; } //在cpu大于1的情况下才会去自旋 if (ngx_ncpu > 1) { //仔细看这个双层for循环随着n的增大nginx_cpu_pause执行的间隔就越大。 for (n = 1; n < spin; n <<= 1) { for (i = 0; i < n; i++) { //架构体系中专门为了自旋锁而提供的指令,它会告诉CPU现在处于自旋锁等待状态,通常一个CPU会将自己置于节能状态,降低功耗。但是当前进程并没有让出正在使用的处理器。 ngx_cpu_pause(); } //尝试去获取锁,尝试获取锁的次数并不多,是spin的一个对数关系,而且时间间隔会越来越大。 if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) { return; } } } //在一个for循环之内usleep(1) 暂时让出处理器 ngx_sched_yield(); } #else #if (NGX_THREADS) #error ngx_spinlock() or ngx_atomic_cmp_set() are not defined ! #endif #endif }
可以看到nginx充分利用了多核和单核的场景,里面的双层for循环其实也是博大精深,其余的细节也格外精辟。自旋锁在短时间锁上面是非常高效和有用的。细致的你,应该会发现在ngx_shmtx_lock方法里面,也采用了自旋锁和信号量一起的方式去实现的。
相关文章推荐
- Nginx下实现pathinfo及ThinkPHP的URL Rewrite模式支持
- nginx状态监控
- 关于 Nginx 并发连接数
- Nginx 限制单个IP的并发连接数及对每个连接速度(限速)
- windows下nginx安装、配置与使用
- nginx服务器报403 forbidden错误的解决办法
- Java+Nginx实现POP、IMAP、SMTP邮箱代理服务
- 【二】nginx源码文件结构浏览
- ubuntu 12.04下编译安装nginx-1.9.3
- 使用virtualenv, uwsgi, nginx来布署flask
- nginx
- Nginx启动停止脚本
- nginx问题总结
- 二、nginx服务器基础配置命令
- CentOS 7 用户怎样安装 LNMP(Nginx+PHP+MySQL)
- Nginx在Linux下的安装部署
- tengine-1.5.2配置session_sticky后不返回session cookie问题解决
- windows下配置nginx+php环境
- 一个centos7上全自动互动式编译nginx的脚本
- Nginx - Windows下Nginx基本安装和配置