zoukankan      html  css  js  c++  java
  • 菜鸟nginx源码剖析数据结构篇(十) 自旋锁ngx_spinlock[转]

    菜鸟nginx源码剖析数据结构篇(十) 自旋锁ngx_spinlock

    • Author:Echo Chen(陈斌)

    • Email:chenb19870707@gmail.com

    • Blog:Blog.csdn.net/chen19870707

    • Date:Nov 11th, 2014

                自旋锁(Spinlock)是一种 Linux 内核中广泛运用的底层同步机制。自旋锁是一种工作于多处理器环境的特殊的锁,在单处理环境中自旋锁的操作被替换为空操作。当某个处理器上的内核执行线程申请自旋锁时,如果锁可用,则获得锁,然后执行临界区操作,最后释放锁;如果锁已被占用,线程并不会转入睡眠状态,而是忙等待该锁,一旦锁被释放,则第一个感知此信息的线程将获得锁。

      1.源代码位置

      源文件:http://trac.nginx.org/nginx/browser/nginx/src/core/ngx_spinlock.c

      2.相关结构定义

      原子锁结构 ngx_atomic_t:

         1: typedef unsigned long               ngx_atomic_uint_t;
         2: typedef volatile ngx_atomic_uint_t  ngx_atomic_t;

      原子锁值类型 ngx_atomic_int_t:

         1: typedef long                        ngx_atomic_int_t;

      原子的比较和交换,如果lock和old相等,则set写入lock

         1: #define ngx_atomic_cmp_set(lock, old, set)                                    
         2:     __sync_bool_compare_and_swap(lock, old, set)

      说明:

      bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...) 
             type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)

      这两个函数是GCC提供原子的比较和交换,如果*ptr == oldval,就将newval写入*ptr。

      进程主动让出执行权,ngx_sched_yeld

         1: #define ngx_sched_yield()  sched_yield()

      3.源代码剖析

         1: void
         2: ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin)
         3: {
         4:  
         5: #if (NGX_HAVE_ATOMIC_OPS)
         6:  
         7:     ngx_uint_t  i, n;
         8:  
         9:  
        10:     for ( ;; ) {
        11:  
        12:         //*lock == 0,没有上锁则上锁,则调用ngx_atomic_cmp_set上锁,设置*lock=value,然后返回 
        13:         if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) {
        14:             return;
        15:         }
        16:         
        17:         // 多核
        18:         if (ngx_ncpu > 1) {
        19:             
        20:             //如果 spin 为 80,则第一次等待 1 个 ngx_cpu_pause() 操作,然后再次查看锁是否可用。接下来每轮分别等待 2个、4 个、8 个、16 个、32 个、64 个 ngx_cpu_pause() 操作后再试。
        21:               //这中间过程中如果出现锁被释放从而可以使用的情况,则循环会被中止,spinlock 函数会返回值。如果重试仍没有成功,则执行 ngx_sched_yield,然后再重复上面的操作。
        22:             for (n = 1; n < spin; n <<= 1) {
        23:  
        24:                 for (i = 0; i < n; i++) {
        25:                     ngx_cpu_pause();
        26:                 }
        27:                 
        28:                 //检查是否上锁,如果 *lock == 0,则迅速上锁返回
        29:                 if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) {
        30:                     return;
        31:                 }
        32:             }
        33:         }
        34:         
        35:         //让出CPU执行权
        36:         ngx_sched_yield();
        37:     }
        38:  
        39: #else
        40:  
        41: #if (NGX_THREADS)
        42:  
        43: #error ngx_spinlock() or ngx_atomic_cmp_set() are not defined !
        44:  
        45: #endif
        46:  
        47: #endif
        48:  
        49: }
    • 4.参考资料

      1.http://blog.csdn.net/poechant/article/details/8062969

      2.《深入理解Nginx》

  • 相关阅读:
    Java NIO3:缓冲区Buffer
    Java NIO2:NIO概述
    Mybatis学习总结(六)——高级映射(一对一,一对多,多对多)
    Java NIO1:浅谈I/O模型
    Java多线程(三)—— synchronized关键字详解
    Java IO(五)——字符流进阶及BufferedWriter、BufferedReader
    Java IO(四)——字符流
    mysql 实现树形的遍历
    Java IO(三)——字节流
    使用 SVN Hook 实现服务器端代码自动更新
  • 原文地址:https://www.cnblogs.com/0x2D-0x22/p/4141307.html
Copyright © 2011-2022 走看看