淺談nginx讀寫鎖的實現邏輯
我們一般認為nginx是一個多進程單線程的應用服務,雖然nginx在一個worker進程內是沒有數據競爭問題的(因為是單線程),但是不免nginx在多個進程間還有一些需要共享的數據,譬如ngx_http_upstream_zone_module模塊將peers數據放在了共享內存中供多個worker進程來使用,又譬如ngx_http_limit_conn_module模塊將并發(fā)連接數限制也放在了共享內存中,諸如此類的,自然會涉及到共享內存訪問的互斥鎖的問題,本文對nginx實現的互斥鎖進行分析,通過分析學習nginx的實現代碼,以便將來可以應用到自己的日常應用程序中去。
nginx的讀寫鎖實現邏輯是通過自旋鎖來實現的。
nginx一共實現了以下幾個api函數:
void ngx_rwlock_wlock(ngx_atomic_t *lock); void ngx_rwlock_rlock(ngx_atomic_t *lock); void ngx_rwlock_unlock(ngx_atomic_t *lock); void ngx_rwlock_downgrade(ngx_atomic_t *lock);
ngx_rwlock_wlock用來加寫鎖,ngx_rwlock_rlock用來加讀鎖,ngx_rwlock_unlock用來對加的鎖進行釋放,ngx_rwlock_downgrade對寫鎖進行降級為讀鎖。
鎖變量是ngx_atomic_t類型,對應的就是一個unsigned long的類型。
以下是ngx_rwlock_wlock的實現代碼:
void ngx_rwlock_wlock(ngx_atomic_t *lock) { ngx_uint_t i, n; for ( ;; ) { /* 如果*lock的值是0表示現在沒有加任何讀寫鎖 ngx_atomic_cmp_set比較如果是lock是0,則將其設置為NGX_RWLOCK_WLOCK 表示加鎖成功,可以返回了 */ if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, NGX_RWLOCK_WLOCK)) { return; } if (ngx_ncpu > 1) { /* 對于多cpu的情況需要進行自旋加鎖檢測 */ for (n = 1; n < NGX_RWLOCK_SPIN; n <<= 1) { for (i = 0; i < n; i++) { ngx_cpu_pause(); } if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, NGX_RWLOCK_WLOCK)) { return; } } } /* 通知os將自己切出,調度到其他進程 */ ngx_sched_yield(); } }
以下是ngx_rwlock_rlock的實現代碼:
void ngx_rwlock_rlock(ngx_atomic_t *lock) { ngx_uint_t i, n; ngx_atomic_uint_t readers; for ( ;; ) { readers = *lock; /* 如果*lock的值不是NGX_RWLOCK_WLOCK表示現在沒有加寫鎖,則可以嘗試獲取讀鎖, ngx_atomic_cmp_set比較如果是lock和之前保存的readers一致, 則將其設置為readers+1,表示加鎖成功,可以返回了 */ if (readers != NGX_RWLOCK_WLOCK && ngx_atomic_cmp_set(lock, readers, readers + 1)) { return; } if (ngx_ncpu > 1) { /* 對于多cpu的情況需要進行自旋加鎖檢測 */ for (n = 1; n < NGX_RWLOCK_SPIN; n <<= 1) { for (i = 0; i < n; i++) { ngx_cpu_pause(); } readers = *lock; if (readers != NGX_RWLOCK_WLOCK && ngx_atomic_cmp_set(lock, readers, readers + 1)) { return; } } } /* 通知os將自己切出,調度到其他進程 */ ngx_sched_yield(); } }
以下是ngx_rwlock_unlock的實現代碼:
void ngx_rwlock_unlock(ngx_atomic_t *lock) { if (*lock == NGX_RWLOCK_WLOCK) { /* 如果是寫鎖定了,那么將*lock置為0,表示沒有加任何鎖了*/ (void) ngx_atomic_cmp_set(lock, NGX_RWLOCK_WLOCK, 0); } else { /*如果當前是讀鎖定了,那么只是將*lock-1,表示少了一個讀者 */ (void) ngx_atomic_fetch_add(lock, -1); } }
以下是ngx_rwlock_downgrade的實現代碼:
void ngx_rwlock_downgrade(ngx_atomic_t *lock) { /* 如果當前是加上了寫鎖的,因為肯定沒有讀者,將自己變?yōu)樽x者,所以只有1個讀者, 因此將*lock設置為1 */ if (*lock == NGX_RWLOCK_WLOCK) { *lock = 1; } }
到此這篇關于淺談nginx讀寫鎖的實現邏輯的文章就介紹到這了,更多相關nginx讀寫鎖內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
WordPress中開啟多站點支持及Nginx的重寫規(guī)則配置
這篇文章主要介紹了WordPress中開啟多站點支持及Nginx的重寫規(guī)則配置方法,在同一個WordPress軟件中開啟的多個站點如果需要綁定不同域名的話也可以使用WordPress MU Domain Mapping插件,需要的朋友可以參考下2016-03-03Nginx跨域設置Access-Control-Allow-Origin無效的解決辦法
今天小編就為大家分享一篇關于Nginx跨域設置Access-Control-Allow-Origin無效的解決辦法,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-02-02