欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang的鎖機(jī)制使用及說(shuō)明

 更新時(shí)間:2023年02月16日 16:05:29   作者:@航空母艦  
這篇文章主要介紹了Golang的鎖機(jī)制使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

golang中的鎖分為互斥鎖、讀寫(xiě)鎖、原子鎖即原子操作。

在 Golang 里有專(zhuān)門(mén)的方法來(lái)實(shí)現(xiàn)鎖,就是 sync 包,這個(gè)包有兩個(gè)很重要的鎖類(lèi)型。一個(gè)叫 Mutex, 利用它可以實(shí)現(xiàn)互斥鎖。

一個(gè)叫 RWMutex,利用它可以實(shí)現(xiàn)讀寫(xiě)鎖。

  • 全局鎖 sync.Mutex,是同一時(shí)刻某一資源只能上一個(gè)鎖,此鎖具有排他性,上鎖后只能被此線(xiàn)程使用,直至解鎖。加鎖后即不能讀也不能寫(xiě)。全局鎖是互斥鎖,即 sync.Mutex 是個(gè)互斥鎖。
  • 讀寫(xiě)鎖 sync.RWMutex ,將使用者分為讀者和寫(xiě)者兩個(gè)概念,支持同時(shí)多個(gè)讀者一起讀共享資源,但寫(xiě)時(shí)只能有一個(gè),并且在寫(xiě)時(shí)不可以讀。理論上來(lái)說(shuō),sync.RWMutex 的 Lock() 也是個(gè)互斥鎖。

踩坑點(diǎn)

將上面的結(jié)論展開(kāi)一下,更清晰得說(shuō)(為避免理解偏差寧可嘮叨一些):

  • sync.Mutex 的鎖是不可以嵌套使用的。
  • sync.RWMutex 的 mu.Lock() 是不可以嵌套的。
  • sync.RWMutex 的 mu.Lock() 中不可以嵌套 mu.RLock()。(這是個(gè)注意的地方)

否則,會(huì) panic fatal error: all goroutines are asleep - deadlock!

var l sync.RWMutex
?
func lockAndRead() { // 可讀鎖內(nèi)使用可讀鎖
?? ?l.RLock()
?? ?defer l.RUnlock()
?
?? ?l.RLock()
?? ?defer l.RUnlock()
}
?
func main() {
?? ?lockAndRead()
?? ?time.Sleep(5 * time.Second)
}

而將 lockAndRead 換為以下三種函數(shù)均會(huì)造成 panic:

func lockAndRead1() { // 全局鎖內(nèi)使用全局鎖
?? ?l.Lock()
?? ?defer l.Unlock()
?
?? ?l.Lock()
?? ?defer l.Unlock()
}
?
func lockAndRead2() { // 全局鎖內(nèi)使用可讀鎖
?? ?l.Lock()
?? ?defer l.Unlock() // 由于 defer 是棧式執(zhí)行,所以這兩個(gè)鎖是嵌套結(jié)構(gòu)
?
?? ?l.RLock()
?? ?defer l.RUnlock()
}
?
func lockAndRead3() { // 可讀鎖內(nèi)使用全局鎖
?? ?l.RLock()
?? ?defer l.RUnlock()
?
?? ?l.Lock()
?? ?defer l.Unlock()
}

互斥鎖 Mutex

互斥鎖有兩個(gè)方法:加鎖、解鎖。

一個(gè)互斥鎖只能同時(shí)被一個(gè) goroutine 鎖定,其它 goroutine 將阻塞直到互斥鎖被解鎖(重新?tīng)?zhēng)搶對(duì)互斥鎖的鎖定)。

使用Lock加鎖后,不能再進(jìn)行加鎖,只有當(dāng)對(duì)其進(jìn)行Unlock解鎖之后,才能對(duì)其加鎖。這個(gè)很好理解。

  • 如果對(duì)一個(gè)未加鎖的資源進(jìn)行解鎖,會(huì)引發(fā)panic異常。
  • 可以在一個(gè)goroutine中對(duì)一個(gè)資源加鎖,而在另外一個(gè)goroutine中對(duì)該資源進(jìn)行解鎖。
  • 不要在持有鎖的時(shí)候做 IO 操作。盡量只通過(guò)持有鎖來(lái)保護(hù) IO 操作需要的資源而不是 IO 操作本身
func (m *Mutex) Lock()
func (m *Mutex) Unlock()

讀寫(xiě)鎖 RWMutex

讀寫(xiě)鎖有四個(gè)方法:讀的加鎖、解鎖,寫(xiě)的加鎖、解鎖。

func ?(*RWMutex)Lock()
func (*RWMutex)Unlock()

func (*RWMutex)RLock()
func (*RWMutex)RUnlock()

RWMutex的使用主要事項(xiàng)

  • 1、讀鎖的時(shí)候無(wú)需等待讀鎖的結(jié)束
  • 2、讀鎖的時(shí)候要等待寫(xiě)鎖的結(jié)束
  • 3、寫(xiě)鎖的時(shí)候要等待讀鎖的結(jié)束
  • 4、寫(xiě)鎖的時(shí)候要等待寫(xiě)鎖的結(jié)束

謹(jǐn)防鎖拷貝

type MyMutex struct {
?? ?count int
?? ?sync.Mutex
}
?
func main() {
?? ?var mu MyMutex
?? ?mu.Lock()
?? ?var mu1 = mu
?? ?mu.count++
?? ?mu.Unlock()
?? ?mu1.Lock()
?? ?mu1.count++
?? ?mu1.Unlock()
?? ?fmt.Println(mu.count, mu1.count)
}

加鎖后復(fù)制變量,會(huì)將鎖的狀態(tài)也復(fù)制,所以 mu1 其實(shí)是已經(jīng)加鎖狀態(tài),再加鎖會(huì)死鎖

查看數(shù)據(jù)競(jìng)爭(zhēng)

加上 -race 參數(shù)驗(yàn)證數(shù)據(jù)競(jìng)爭(zhēng)

以下代碼有什么問(wèn)題,怎么解決?

func main() {
?? ?total, sum := 0, 0
?? ?for i := 1; i <= 10; i++ {
?? ??? ?sum += i
?? ??? ?go func() {
?? ??? ??? ?total += i
?? ??? ?}()
?? ?}
?? ?fmt.Printf("total:%d sum %d", total, sum)
}

該題的第二個(gè)考點(diǎn):data race。

因?yàn)榇嬖诙?goroutine 同時(shí)寫(xiě) total 變量的問(wèn)題,所以有數(shù)據(jù)競(jìng)爭(zhēng)。

可以加上 -race 參數(shù)驗(yàn)證

go run -race main.go
==================
WARNING: DATA RACE
Read at 0x00c0001b4020 by goroutine 8:
? main.main.func1()
? ? ? /Users/xuxinhua/main.go:12 +0x57
?
Previous write at 0x00c0001b4020 by main goroutine:
? main.main()
? ? ? /Users/xuxinhua/main.go:9 +0x10b
?
Goroutine 8 (running) created at:
? main.main()
? ? ? /Users/xuxinhua/main.go:11 +0xe7
==================

正確答案

package main
?
import (
? ? "sync/atomic"
? ? "sync"
? ? "fmt"
)
?
func main() {
? ? var wg sync.WaitGroup
? ? var total int64
? ? sum := 0
? ? for i := 1; i <= 10; i++ {
? ? ? ? wg.Add(1)
? ? ? ? sum += i
? ? ? ? go func(i int) {
? ? ? ? ? ? defer wg.Done()
? ? ? ? ? ? atomic.AddInt64(&total, int64(i))
? ? ? ? }(i)
? ? }
? ? wg.Wait()
?
? ? fmt.Printf("total:%d sum %d", total, sum)
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • go語(yǔ)言中strings包的用法匯總

    go語(yǔ)言中strings包的用法匯總

    Golang語(yǔ)言 strings標(biāo)準(zhǔn)庫(kù)包主要涉及字符串的基本操作,下面我們來(lái)詳細(xì)分析下吧
    2018-10-10
  • 詳解Go語(yǔ)言中的內(nèi)存對(duì)齊

    詳解Go語(yǔ)言中的內(nèi)存對(duì)齊

    前面我們學(xué)習(xí)了Go語(yǔ)言空結(jié)構(gòu)體詳解,最近又在看unsafe包的知識(shí),在查閱相關(guān)資料時(shí)不免會(huì)看到內(nèi)存對(duì)齊相關(guān)的內(nèi)容。雖然不會(huì),但可以學(xué)呀,那么這篇文章,我們就一起來(lái)看下什么是內(nèi)存對(duì)齊吧
    2022-10-10
  • golang中的defer函數(shù)理解

    golang中的defer函數(shù)理解

    defer是Go語(yǔ)言中的延遲執(zhí)行語(yǔ)句,用來(lái)添加函數(shù)結(jié)束時(shí)執(zhí)行的代碼,常用于釋放某些已分配的資源、關(guān)閉數(shù)據(jù)庫(kù)連接、斷開(kāi)socket連接、解鎖一個(gè)加鎖的資源,這篇文章主要介紹了golang中的defer函數(shù)理解,需要的朋友可以參考下
    2022-10-10
  • Go語(yǔ)言實(shí)現(xiàn)二維數(shù)組的2種遍歷方式以及案例詳解

    Go語(yǔ)言實(shí)現(xiàn)二維數(shù)組的2種遍歷方式以及案例詳解

    這篇文章主要介紹了Go語(yǔ)言實(shí)現(xiàn)二維數(shù)組的2種遍歷方式以及案例詳解,圖文代碼聲情并茂,有感興趣的可以學(xué)習(xí)下
    2021-03-03
  • 手把手帶你走進(jìn)Go語(yǔ)言之運(yùn)算符解析

    手把手帶你走進(jìn)Go語(yǔ)言之運(yùn)算符解析

    這篇文章主要介紹了手Go語(yǔ)言之運(yùn)算符解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • Go指針內(nèi)存與安全性深入理解

    Go指針內(nèi)存與安全性深入理解

    這篇文章主要為大家介紹了Go指針內(nèi)存與安全性深入理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Go語(yǔ)言之重要數(shù)組類(lèi)型切片(slice)make,append函數(shù)解讀

    Go語(yǔ)言之重要數(shù)組類(lèi)型切片(slice)make,append函數(shù)解讀

    這篇文章主要介紹了Go語(yǔ)言之重要數(shù)組類(lèi)型切片(slice)make,append函數(shù)用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • go中的protobuf和grpc使用教程

    go中的protobuf和grpc使用教程

    gRPC 是 Google 公司基于 Protobuf 開(kāi)發(fā)的跨語(yǔ)言的開(kāi)源 RPC 框架,這篇文章主要介紹了go中的protobuf和grpc使用教程,需要的朋友可以參考下
    2024-08-08
  • Golang自定義開(kāi)發(fā)Prometheus?exporter詳解

    Golang自定義開(kāi)發(fā)Prometheus?exporter詳解

    Exporter是基于Prometheus實(shí)施的監(jiān)控系統(tǒng)中重要的組成部分,承擔(dān)數(shù)據(jù)指標(biāo)的采集工作,這篇文章主要為大家介紹了如何自定義編寫(xiě)開(kāi)發(fā)?Prometheus?exporter,感興趣的可以了解一下
    2023-06-06
  • 詳解Go?中的時(shí)間處理

    詳解Go?中的時(shí)間處理

    這篇文章主要介紹了Go?中的時(shí)間處理,本文將介紹?time?庫(kù)中一些重要的函數(shù)和方法,希望能幫助到那些一遇到?Go?時(shí)間處理問(wèn)題就需要百度的童鞋,需要的朋友可以參考下
    2022-07-07

最新評(píng)論