淺談nginx讀寫鎖的實(shí)現(xiàn)邏輯
我們一般認(rèn)為nginx是一個多進(jìn)程單線程的應(yīng)用服務(wù),雖然nginx在一個worker進(jìn)程內(nèi)是沒有數(shù)據(jù)競爭問題的(因?yàn)槭菃尉€程),但是不免nginx在多個進(jìn)程間還有一些需要共享的數(shù)據(jù),譬如ngx_http_upstream_zone_module模塊將peers數(shù)據(jù)放在了共享內(nèi)存中供多個worker進(jìn)程來使用,又譬如ngx_http_limit_conn_module模塊將并發(fā)連接數(shù)限制也放在了共享內(nèi)存中,諸如此類的,自然會涉及到共享內(nèi)存訪問的互斥鎖的問題,本文對nginx實(shí)現(xiàn)的互斥鎖進(jìn)行分析,通過分析學(xué)習(xí)nginx的實(shí)現(xiàn)代碼,以便將來可以應(yīng)用到自己的日常應(yīng)用程序中去。
nginx的讀寫鎖實(shí)現(xiàn)邏輯是通過自旋鎖來實(shí)現(xiàn)的。
nginx一共實(shí)現(xiàn)了以下幾個api函數(shù):
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用來對加的鎖進(jìn)行釋放,ngx_rwlock_downgrade對寫鎖進(jìn)行降級為讀鎖。
鎖變量是ngx_atomic_t類型,對應(yīng)的就是一個unsigned long的類型。
以下是ngx_rwlock_wlock的實(shí)現(xiàn)代碼:
void ngx_rwlock_wlock(ngx_atomic_t *lock) { ngx_uint_t i, n; for ( ;; ) { /* 如果*lock的值是0表示現(xiàn)在沒有加任何讀寫鎖 ngx_atomic_cmp_set比較如果是lock是0,則將其設(shè)置為NGX_RWLOCK_WLOCK 表示加鎖成功,可以返回了 */ if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, NGX_RWLOCK_WLOCK)) { return; } if (ngx_ncpu > 1) { /* 對于多cpu的情況需要進(jìn)行自旋加鎖檢測 */ 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將自己切出,調(diào)度到其他進(jìn)程 */ ngx_sched_yield(); } }
以下是ngx_rwlock_rlock的實(shí)現(xiàn)代碼:
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表示現(xiàn)在沒有加寫鎖,則可以嘗試獲取讀鎖, ngx_atomic_cmp_set比較如果是lock和之前保存的readers一致, 則將其設(shè)置為readers+1,表示加鎖成功,可以返回了 */ if (readers != NGX_RWLOCK_WLOCK && ngx_atomic_cmp_set(lock, readers, readers + 1)) { return; } if (ngx_ncpu > 1) { /* 對于多cpu的情況需要進(jìn)行自旋加鎖檢測 */ 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將自己切出,調(diào)度到其他進(jìn)程 */ ngx_sched_yield(); } }
以下是ngx_rwlock_unlock的實(shí)現(xiàn)代碼:
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 { /*如果當(dāng)前是讀鎖定了,那么只是將*lock-1,表示少了一個讀者 */ (void) ngx_atomic_fetch_add(lock, -1); } }
以下是ngx_rwlock_downgrade的實(shí)現(xiàn)代碼:
void ngx_rwlock_downgrade(ngx_atomic_t *lock) { /* 如果當(dāng)前是加上了寫鎖的,因?yàn)榭隙]有讀者,將自己變?yōu)樽x者,所以只有1個讀者, 因此將*lock設(shè)置為1 */ if (*lock == NGX_RWLOCK_WLOCK) { *lock = 1; } }
到此這篇關(guān)于淺談nginx讀寫鎖的實(shí)現(xiàn)邏輯的文章就介紹到這了,更多相關(guān)nginx讀寫鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
WordPress中開啟多站點(diǎn)支持及Nginx的重寫規(guī)則配置
這篇文章主要介紹了WordPress中開啟多站點(diǎn)支持及Nginx的重寫規(guī)則配置方法,在同一個WordPress軟件中開啟的多個站點(diǎn)如果需要綁定不同域名的話也可以使用WordPress MU Domain Mapping插件,需要的朋友可以參考下2016-03-03Nginx跨域設(shè)置Access-Control-Allow-Origin無效的解決辦法
今天小編就為大家分享一篇關(guān)于Nginx跨域設(shè)置Access-Control-Allow-Origin無效的解決辦法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-02-02Nginx配置四層、七層網(wǎng)絡(luò)代理轉(zhuǎn)發(fā)的方法示例
nginx作為透明代理可以充分利用其高性能和靈活性來實(shí)現(xiàn)網(wǎng)絡(luò)流量的轉(zhuǎn)發(fā)和處理,本文主要介紹了Nginx配置四層、七層網(wǎng)絡(luò)代理轉(zhuǎn)發(fā)的方法示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03nginx訪問日志并刪除指定天數(shù)前的日志記錄配置方法
這篇文章主要介紹了nginx訪問日志并刪除指定天數(shù)前的日志記錄配置方法,需要的朋友可以參考下2014-03-03Nginx與Lua灰度發(fā)布的實(shí)現(xiàn)
這篇文章主要介紹了Nginx與Lua灰度發(fā)布的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03