golang非阻塞鎖的簡單實現

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

對於複雜類型如 container/list ,需要在所有讀寫操作上使用 sync.mutex 互斥鎖以保證資料一致性,互斥鎖並發情況下,Lock 操作會阻塞,一直等到其他線程Unlock,但是有的時候因為有一個耗時比較長的操作一直佔用鎖,我們想讓其他線程不在Lock上一直阻塞,而是直接走其他商務程序。

舉一個很簡單的情境:在多人並發抽獎環節,為了保證不出現負庫存,我們可以通過競爭鎖,第一個擷取鎖的人可能中獎,而其他並發過來的請求擷取鎖失敗(而不是一直阻塞在Lock()),直接當做未中獎處理。

思考了一下,有一個思路,我們可以用兩道鎖,第一道鎖用來判斷鎖狀態,第二道鎖才是真正的耗時任務用的鎖。

直接上代碼

type NBLocker struct{l1 sync.Mutexl2 sync.Mutexlocked bool}func (NBLocker *NBLocker) Lock() (success bool) {NBLocker.l1.Lock()defer NBLocker.l1.Unlock()if NBLocker.locked == false {NBLocker.locked = truesuccess = trueNBLocker.l2.Lock()}return}func (NBLocker *NBLocker) Unlock() {NBLocker.l1.Lock()defer NBLocker.l1.Unlock()NBLocker.locked = falseNBLocker.l2.Unlock()}

使用

type foo struct {mux NBLocker}func (self *foo) Bong(wg *sync.WaitGroup) {defer wg.Done()if !self.mux.Lock() {fmt.Println("擷取鎖失敗")return}defer self.mux.Unlock()time.Sleep(time.Second) //停頓一秒fmt.Println("bong~")}func main() {f := &foo{}wg := &sync.WaitGroup{}wg.Add(4)go f.Bong(wg)go f.Bong(wg)go f.Bong(wg)time.Sleep(time.Second *2)go f.Bong(wg)wg.Wait()}

如果擷取第二道鎖失敗,NBLocker.Lock() 方法會直接返回false,這時候只需要判斷一下就可以直接跳過"抽獎環節"

以上常式輸出

擷取鎖失敗擷取鎖失敗bong~bong~

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.