亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Go中sync.Mutex 加鎖失效的問(wèn)題解決

 更新時(shí)間:2024年08月20日 10:22:51   作者:Looooking  
sync.Mutex是Go標(biāo)準(zhǔn)庫(kù)中常用的一個(gè)排外鎖,本文主要介紹了Go中sync.Mutex 加鎖失效的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

我先聲明一下,并不是真的加鎖失效,而是我之前的理解有誤,導(dǎo)致看起來(lái)像是加鎖失效一樣。于是乎記錄一下,加深一下印象。

我之前有個(gè)理解誤區(qū)(不知道大家有沒(méi)有,有的話(huà)趕緊糾正一下——其實(shí)也是因?yàn)槲疫@塊的知識(shí)掌握不牢固導(dǎo)致的):覺(jué)得只要是加鎖后,在我主動(dòng)調(diào)用解鎖之前,這個(gè)塊范圍內(nèi)的變量一定不會(huì)被其他地方修改。后來(lái)驗(yàn)證發(fā)現(xiàn),我大錯(cuò)特錯(cuò)了。

起因

最近在學(xué)習(xí) sync.Mutex 加鎖時(shí),寫(xiě)了下面一段代碼進(jìn)行練習(xí)。

package main

import (
	"fmt"
	"sync"
	"time"
)


type Info struct {
	mu sync.Mutex
	Value string
}

func Update(info *Info) {
	fmt.Printf("%s: before update. Value: %s\n", time.Now().Format(timeFormat), info.Value)
	info.mu.Lock()
	defer info.mu.Unlock()
	time.Sleep(2 * time.Second)
	fmt.Printf("%s: in update. Value: %s\n", time.Now().Format(timeFormat), info.Value)
	info.Value = "update"
	fmt.Printf("%s: after update. Value: %s\n", time.Now().Format(timeFormat), info.Value)
}

const timeFormat = "2006-01-02 15:04:05"

func main() {
	fmt.Printf("%s: main start\n", time.Now().Format(timeFormat))
	info := &Info{}
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		Update(info)
	}()
	time.Sleep(time.Second)
	info.Value = "main"
	fmt.Printf("%s: in main. Value: %s\n", time.Now().Format(timeFormat), info.Value)
	wg.Wait()
}

按照我原先上面的理解,Update() 函數(shù)當(dāng)中,before update 和 in update 中對(duì)應(yīng)結(jié)構(gòu)體的值應(yīng)該是不會(huì)變的(畢竟我加了鎖)。然而從運(yùn)行結(jié)果發(fā)現(xiàn),Update() 函數(shù)執(zhí)行期間,結(jié)構(gòu)體變量的 Value 竟然還是被外部主線(xiàn)程修改了。

分析

那么為什么會(huì)這樣呢?明明 Update() 里邊已經(jīng)添加了鎖,為什么執(zhí)行期間還是會(huì)被其他地方修改呢?

最后發(fā)現(xiàn),究其原因,還是在于主線(xiàn)程修改變量的值的時(shí)候,沒(méi)有先判斷鎖 mu 是否已經(jīng)釋放,就直接進(jìn)行了修改操作。

主線(xiàn)程中加上獲取鎖的操作后,會(huì)先判斷當(dāng)前鎖是否被釋放,如果沒(méi)被釋放,就會(huì)一直進(jìn)行等待直到鎖釋放后才繼續(xù)執(zhí)行后面的操作。

輸出結(jié)果也和預(yù)期保持一致 。

2024-04-16 23:59:13: main start
2024-04-16 23:59:13: before update. Value: 
2024-04-16 23:59:15: in update. Value: 
2024-04-16 23:59:15: after update. Value: update
2024-04-16 23:59:15: in main. Value: main

正常來(lái)說(shuō),鎖是要配合多 goroutine 來(lái)使用的, 對(duì)于單線(xiàn)程來(lái)說(shuō),由于沒(méi)有其他線(xiàn)程進(jìn)行資源競(jìng)爭(zhēng),加鎖的意義不大;對(duì)于多 goroutine 而言,對(duì)于獲取和釋放鎖的時(shí)機(jī),應(yīng)該由應(yīng)用程序合理控制。關(guān)于鎖的使用,還有一些其他注意事項(xiàng),這塊也一并寫(xiě)一下。

  • 在一個(gè) goroutine 獲得 Mutex 后,其他 goroutine 只能等到這個(gè) goroutine 釋放該 Mutex
  • 使用 Lock() 加鎖后,不能再繼續(xù)對(duì)其加鎖,直到利用 Unlock() 解鎖后才能再加鎖
  • 在 Lock() 之前使用 Unlock() 會(huì)導(dǎo)致 panic 異常
  • 已經(jīng)鎖定的 Mutex 并不與特定的 goroutine 相關(guān)聯(lián),這樣可以利用一個(gè) goroutine 對(duì)其加鎖,再利用其他 goroutine 對(duì)其解鎖
  • 在同一個(gè) goroutine 中的 Mutex 解鎖之前再次進(jìn)行加鎖,會(huì)導(dǎo)致死鎖
  • 適用于讀寫(xiě)不確定,并且只有一個(gè)讀或者寫(xiě)的場(chǎng)景

緩沖通道實(shí)現(xiàn)互斥邏輯

當(dāng)然,我們還可以通過(guò)緩沖為1的通道實(shí)現(xiàn)互斥鎖的邏輯。

package main

import (
	"fmt"
	"sync"
	"time"
)


type Info struct {
	Value string
}

func Update(info *Info, sem chan bool) {
	fmt.Printf("%s: before update. Value: %s\n", time.Now().Format(timeFormat), info.Value)
	sem <- true
	defer func() {
		<- sem
	}()
	time.Sleep(2 * time.Second)
	fmt.Printf("%s: in update. Value: %s\n", time.Now().Format(timeFormat), info.Value)
	info.Value = "update"
	fmt.Printf("%s: after update. Value: %s\n", time.Now().Format(timeFormat), info.Value)
}

const timeFormat = "2006-01-02 15:04:05"

func main() {
	sem := make(chan bool, 1)
	fmt.Printf("%s: main start\n", time.Now().Format(timeFormat))
	info := &Info{}
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		Update(info, sem)
	}()
	time.Sleep(time.Second)
	sem <- true
	info.Value = "main"
	fmt.Printf("%s: in main. Value: %s\n", time.Now().Format(timeFormat), info.Value)
	<- sem
	wg.Wait()
}

2024-04-17 00:26:25: main start
2024-04-17 00:26:25: before update. Value: 
2024-04-17 00:26:26: in main. Value: main
2024-04-17 00:26:27: in update. Value: main
2024-04-17 00:26:27: after update. Value: update

到此這篇關(guān)于Go中sync.Mutex 加鎖失效的問(wèn)題解決的文章就介紹到這了,更多相關(guān)Go sync.Mutex 加鎖失效內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Go實(shí)現(xiàn)比較時(shí)間大小

    Go實(shí)現(xiàn)比較時(shí)間大小

    這篇文章主要介紹了Go實(shí)現(xiàn)比較時(shí)間大小的方法和示例,非常的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。
    2015-04-04
  • Golang連接Redis數(shù)據(jù)庫(kù)的方法

    Golang連接Redis數(shù)據(jù)庫(kù)的方法

    這篇文章主要介紹了Golang連接Redis數(shù)據(jù)庫(kù)的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • GoLang協(xié)程庫(kù)libtask學(xué)習(xí)筆記

    GoLang協(xié)程庫(kù)libtask學(xué)習(xí)筆記

    libtask一個(gè)C語(yǔ)言的協(xié)程庫(kù),是go語(yǔ)言的前身很早期的原型. 測(cè)試機(jī)器是我的mac air 安裝的centos虛擬機(jī)(只有一個(gè)核), 代碼沒(méi)有采用任何優(yōu)化,只是使用默認(rèn)配置
    2022-12-12
  • 詳解Go語(yǔ)言Slice作為函數(shù)參數(shù)的使用

    詳解Go語(yǔ)言Slice作為函數(shù)參數(shù)的使用

    Slice切片在Go語(yǔ)言中實(shí)質(zhì)是一種結(jié)構(gòu)體類(lèi)型,本文詳細(xì)的介紹了Go語(yǔ)言Slice作為函數(shù)參數(shù)的使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Go語(yǔ)言里的結(jié)構(gòu)體文法實(shí)例分析

    Go語(yǔ)言里的結(jié)構(gòu)體文法實(shí)例分析

    這篇文章主要介紹了Go語(yǔ)言里的結(jié)構(gòu)體文法,實(shí)例分析了結(jié)構(gòu)體文法的概念及使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • 下載golang.org/x包的操作方法

    下載golang.org/x包的操作方法

    今天小編就為大家分享一篇下載golang.org/x包的操作方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • 舉例詳解Go語(yǔ)言中os庫(kù)的常用函數(shù)用法

    舉例詳解Go語(yǔ)言中os庫(kù)的常用函數(shù)用法

    這篇文章主要介紹了Go語(yǔ)言中os庫(kù)的常用函數(shù)用法,os函數(shù)的使用是Go語(yǔ)言入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-10-10
  • 淺談golang類(lèi)型斷言,失敗類(lèi)型斷言返回值問(wèn)題

    淺談golang類(lèi)型斷言,失敗類(lèi)型斷言返回值問(wèn)題

    這篇文章主要介紹了淺談golang類(lèi)型斷言,失敗類(lèi)型斷言返回值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • golang?pprof監(jiān)控memory?block?mutex統(tǒng)計(jì)原理分析

    golang?pprof監(jiān)控memory?block?mutex統(tǒng)計(jì)原理分析

    這篇文章主要為大家介紹了golang?pprof監(jiān)控memory?block?mutex統(tǒng)計(jì)原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Golang的md5 hash計(jì)算操作

    Golang的md5 hash計(jì)算操作

    這篇文章主要介紹了Golang的md5 hash計(jì)算操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12

最新評(píng)論