nginx 鎖實(shí)現(xiàn)思路

鎖從功能上劃分主要有互斥鎖和讀寫鎖。

不主動(dòng)釋放CPU的鎖是spinlock,可以用于競爭較少并且臨界區(qū)較小的場景,也可以用于中斷上下文中。

鎖一般用信號量、原子操作(cas)或文件鎖來實(shí)現(xiàn)。

nginx中實(shí)現(xiàn)了互斥鎖和讀寫鎖以及spinlock。

互斥鎖

加鎖:

lock是一個(gè)原子變量,0表示沒有上鎖,ngx_pid表示被對應(yīng)的進(jìn)程加鎖,如果當(dāng)前被其它進(jìn)程加鎖,說明其它進(jìn)程正在執(zhí)行臨界區(qū)內(nèi)的代碼,不會(huì)馬上釋放鎖,所以會(huì)根據(jù)spin一會(huì)兒再嘗試加鎖,如果不spin而一直不斷嘗試訪問共享變量將會(huì)增加核間通信的負(fù)擔(dān),ngx_cpu_pause()防止循環(huán)代碼被優(yōu)化。

支持posix信號量的情況下,如果spin幾次都沒有加鎖成功則使用信號量進(jìn)行排隊(duì),wait表示排隊(duì)的個(gè)數(shù)。

循環(huán)調(diào)用sem_wait(&mtx->sem) 將進(jìn)程阻塞等待其它進(jìn)程釋放鎖,其它進(jìn)程釋放鎖時(shí)會(huì)檢查是否有進(jìn)程進(jìn)行wait,如果有則通過信號量wakeup正在wait的一個(gè)進(jìn)程,用信號量避免一直占用CPU。

解鎖:

解鎖就是將lock賦值為0。然后會(huì)調(diào)用ngx_shmtx_wakeup(mtx)函數(shù)。

wakeup函數(shù)檢查當(dāng)前有沒有進(jìn)程在排隊(duì),如果有排隊(duì)的進(jìn)程,則通過sem_post(&mtx->sem)激活一個(gè)排隊(duì)的進(jìn)程。

這個(gè)for循環(huán)是一個(gè)小技巧,先將wait共享變量保存在本地局部變量中,然后對wait進(jìn)行檢查,最后再通過cas修改wait共享變量,如果在這中間wait變量被其它進(jìn)程修改,那么本次cas就是失敗,這樣就可以保證將wait檢查和wait修改兩個(gè)步驟原子執(zhí)行,這也是樂觀鎖的實(shí)現(xiàn)。

讀寫鎖

nginx實(shí)現(xiàn)的讀寫鎖對寫鎖不太友好,可能會(huì)有寫鎖饑餓的問題。

#define NGX_RWLOCK_WLOCK ((ngx_atomic_uint_t) -1) 定義寫鎖宏

加寫鎖:

沒有鎖的時(shí)候加寫鎖。

加讀鎖:

加讀鎖的時(shí)候依然用到了上面的技巧,如果沒有加寫鎖,則加讀共享鎖。

解鎖:

先解寫鎖,再解讀鎖。

spinlock

加鎖:

spinlock加鎖居然也會(huì)調(diào)用yield,說明這個(gè)spinlock目前只能用于進(jìn)程上下文。

解鎖:

#define ngx_unlock(lock) *(lock) = 0

這個(gè)地方?jīng)]有指明內(nèi)存序會(huì)不會(huì)有問題呢?我理解其它進(jìn)程會(huì)在本進(jìn)程解鎖的一段時(shí)間之后才會(huì)發(fā)現(xiàn)這次解鎖,會(huì)不會(huì)造成饑餓?待研究。

讀寫鎖(優(yōu)先寫鎖)

加寫鎖:

如果當(dāng)前無鎖,則加寫鎖,如果當(dāng)前被上鎖,則通過信號量等待。

加讀鎖:

如果當(dāng)前不是寫鎖并且隊(duì)列中沒有等待的寫鎖,則加讀鎖,否則自旋加讀鎖。

解鎖:

解寫鎖,然后weakup等待的寫鎖。

解讀鎖,如果讀鎖全部完成,然后weakup等待的寫鎖。

weakup函數(shù)不變,如果wait不為0,則激活一個(gè)寫鎖。不知道是不是正確啊,哈哈

也看到用兩個(gè)互斥鎖實(shí)現(xiàn)讀寫鎖的例子,僅使用互斥鎖實(shí)現(xiàn)讀寫鎖,有才啊?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 臨界區(qū) 1.1簡介 在早期計(jì)算機(jī)系統(tǒng)中,只有一個(gè)任務(wù)進(jìn)程在執(zhí)行,并不存在資源的共享與競爭。隨著技術(shù)和需求的飛速...
    Fly晴天里Fly閱讀 9,197評論 2 13
  • 接著上上節(jié) thread ,本節(jié)主要介紹mutex的內(nèi)容,練習(xí)代碼地址。<mutex>:該頭文件主要聲明了與互斥量...
    jorion閱讀 12,699評論 2 4
  • 本文系轉(zhuǎn)載》》》》》》》》》》》》》》》》 編者按:高可用架構(gòu)分享及傳播在架構(gòu)領(lǐng)域具有典型意義的文章,本文由陳科在...
    demop閱讀 8,377評論 0 7
  • 【校園】這世界的骯臟與你無關(guān)(11) 從學(xué)校方向向東再過一條街是農(nóng)貿(mào)一條街,她們在街口分手,約好晚上的見...
    東邊的耳朵閱讀 279評論 0 4
  • 武漢終于出太陽了。一年之計(jì)在于春,看到太陽的那一刻讓我意識到我,這是一個(gè)萬物復(fù)蘇的季節(jié),而我們也應(yīng)該開膀子加...
    洋仔WyaNG閱讀 154評論 0 0

友情鏈接更多精彩內(nèi)容