聊聊Golang的讀寫鎖
Go語(yǔ)言中的RWMutex是一種讀寫鎖,它采用了讀寫分離的思想,可以同時(shí)支持多個(gè)讀操作,但只能同時(shí)有一個(gè)寫操作。它的原理是這樣的:
- RWMutex內(nèi)部維護(hù)兩個(gè)計(jì)數(shù)器,一個(gè)是讀計(jì)數(shù)器,一個(gè)是寫計(jì)數(shù)器。
- 在讀操作執(zhí)行時(shí),讀計(jì)數(shù)器會(huì)加1,如果此時(shí)寫計(jì)數(shù)器的值不為0,則說(shuō)明有寫操作正在進(jìn)行,那么這個(gè)讀操作就需要阻塞等待。
- 在寫操作執(zhí)行時(shí),會(huì)先判斷讀計(jì)數(shù)器的值是否為0,如果不為0,則說(shuō)明有讀操作正在進(jìn)行,那么這個(gè)寫操作就需要阻塞等待。寫操作執(zhí)行時(shí),會(huì)把寫計(jì)數(shù)器加1,這樣其他讀寫操作就無(wú)法繼續(xù)執(zhí)行了。
- 當(dāng)讀操作執(zhí)行完畢時(shí),讀計(jì)數(shù)器會(huì)減1,如果此時(shí)讀計(jì)數(shù)器的值為0,那么說(shuō)明沒(méi)有其他讀操作在進(jìn)行了,可以允許寫操作了。
- 當(dāng)寫操作執(zhí)行完畢時(shí),寫計(jì)數(shù)器會(huì)減1,如果此時(shí)寫計(jì)數(shù)器的值為0,那么說(shuō)明沒(méi)有其他讀寫操作在進(jìn)行了,此時(shí)其他讀寫操作就可以繼續(xù)執(zhí)行了。
當(dāng)有大量讀時(shí),寫操作不會(huì)餓死,這是因?yàn)樽x寫鎖支持優(yōu)先處理寫操作的。具體來(lái)說(shuō),當(dāng)一個(gè)寫操作請(qǐng)求鎖時(shí),如果此時(shí)已經(jīng)有其他讀或?qū)懖僮鞒钟墟i,那么該寫操作會(huì)被阻塞,等待其他操作釋放鎖。但是,一旦沒(méi)有任何讀或?qū)懖僮鞒钟墟i,那么該寫操作會(huì)立即獲取到鎖,并且優(yōu)先執(zhí)行,即使此時(shí)已經(jīng)有很多讀操作在等待。
也就是說(shuō)讀寫鎖并不是公平鎖。因?yàn)椴⒉槐WC等待時(shí)間最長(zhǎng)的線程能夠最先獲取鎖。
如果需要使用公平鎖,可以考慮使用sync.Mutex,它保證等待時(shí)間最長(zhǎng)的線程能夠最先獲取鎖。但是需要注意的是,公平鎖會(huì)導(dǎo)致額外的開銷,因?yàn)樗枰S護(hù)等待隊(duì)列,進(jìn)行線程切換等操作。