最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

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

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

踩坑點(diǎn)

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

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

否則,會 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ù)均會造成 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í)行,所以這兩個鎖是嵌套結(jié)構(gòu)
?
?? ?l.RLock()
?? ?defer l.RUnlock()
}
?
func lockAndRead3() { // 可讀鎖內(nèi)使用全局鎖
?? ?l.RLock()
?? ?defer l.RUnlock()
?
?? ?l.Lock()
?? ?defer l.Unlock()
}

互斥鎖 Mutex

互斥鎖有兩個方法:加鎖、解鎖。

一個互斥鎖只能同時被一個 goroutine 鎖定,其它 goroutine 將阻塞直到互斥鎖被解鎖(重新爭搶對互斥鎖的鎖定)。

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

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

讀寫鎖 RWMutex

讀寫鎖有四個方法:讀的加鎖、解鎖,寫的加鎖、解鎖。

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

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

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

  • 1、讀鎖的時候無需等待讀鎖的結(jié)束
  • 2、讀鎖的時候要等待寫鎖的結(jié)束
  • 3、寫鎖的時候要等待讀鎖的結(jié)束
  • 4、寫鎖的時候要等待寫鎖的結(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ù)制變量,會將鎖的狀態(tài)也復(fù)制,所以 mu1 其實(shí)是已經(jīng)加鎖狀態(tài),再加鎖會死鎖

查看數(shù)據(jù)競爭

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

以下代碼有什么問題,怎么解決?

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)
}

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

因?yàn)榇嬖诙?goroutine 同時寫 total 變量的問題,所以有數(shù)據(jù)競爭。

可以加上 -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é)

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

相關(guān)文章

  • Golang實(shí)現(xiàn)獲取與解析命令行參數(shù)

    Golang實(shí)現(xiàn)獲取與解析命令行參數(shù)

    這篇文章主要為大家詳細(xì)介紹了Golang如何實(shí)現(xiàn)獲取與解析命令行參數(shù),文中的示例代碼講解詳細(xì),具有一定的借鑒價值,需要的小伙伴可以參考一下
    2024-01-01
  • Go語言題解LeetCode599兩個列表的最小索引總和

    Go語言題解LeetCode599兩個列表的最小索引總和

    這篇文章主要為大家介紹了Go語言題解LeetCode599兩個列表的最小索引總和示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 一文詳解Go語言單元測試的原理與使用

    一文詳解Go語言單元測試的原理與使用

    Go語言中自帶有一個輕量級的測試框架testing和自帶的go?test命令來實(shí)現(xiàn)單元測試和性能測試。本文將通過示例詳細(xì)聊聊Go語言單元測試的原理與使用,需要的可以參考一下
    2022-09-09
  • golang json數(shù)組拼接的實(shí)例

    golang json數(shù)組拼接的實(shí)例

    這篇文章主要介紹了golang json數(shù)組拼接的實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Golang數(shù)據(jù)類型比較詳解

    Golang數(shù)據(jù)類型比較詳解

    這篇文章主要圍繞Golang數(shù)據(jù)類型比較詳細(xì)展開,文中有詳細(xì)的比較過程,需要的朋友可以參考一下
    2023-04-04
  • Go與Rust高性能解析JSON實(shí)現(xiàn)方法示例

    Go與Rust高性能解析JSON實(shí)現(xiàn)方法示例

    這篇文章主要為大家介紹了Go與Rust高性能的解析JSON實(shí)現(xiàn)方法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Go?Ginrest實(shí)現(xiàn)一個RESTful接口

    Go?Ginrest實(shí)現(xiàn)一個RESTful接口

    這篇文章主要為大家介紹了Go?Ginrest實(shí)現(xiàn)一個RESTful接口示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Golang拾遺之指針和接口的使用詳解

    Golang拾遺之指針和接口的使用詳解

    拾遺主要是收集和golang相關(guān)的瑣碎知識,這篇文章主要是為大家整理了Golang中指針和接口的使用方法,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2023-02-02
  • Go與C語言的互操作實(shí)現(xiàn)

    Go與C語言的互操作實(shí)現(xiàn)

    在Go與C語言互操作方面,Go更是提供了強(qiáng)大的支持。尤其是在Go中使用C,你甚至可以直接在Go源文件中編寫C代碼,本文就詳細(xì)的介紹一下如何使用,感興趣的可以了解一下
    2021-12-12
  • Go語言實(shí)現(xiàn)的排列組合問題實(shí)例(n個數(shù)中取m個)

    Go語言實(shí)現(xiàn)的排列組合問題實(shí)例(n個數(shù)中取m個)

    這篇文章主要介紹了Go語言實(shí)現(xiàn)的排列組合問題,結(jié)合實(shí)例形式分析了Go語言實(shí)現(xiàn)排列組合數(shù)學(xué)運(yùn)算的原理與具體操作技巧,需要的朋友可以參考下
    2017-02-02

最新評論

靖宇县| 沭阳县| 江华| 荃湾区| 濮阳市| 农安县| 开阳县| 增城市| 曲松县| 临夏市| 论坛| 仙游县| 高青县| 行唐县| 新竹县| 祁阳县| 遵义市| 沈阳市| 洱源县| 泽州县| 扎赉特旗| 仙桃市| 封丘县| 崇明县| 广元市| 诸城市| 苗栗市| 嘉荫县| 大荔县| 平阴县| 隆子县| 秀山| 海南省| 垦利县| 湘阴县| 黑水县| 邳州市| 大余县| 普兰县| 望江县| 延寿县|