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

Go中sync.Mutex 加鎖失效的問題解決

 更新時間:2024年08月20日 10:22:51   作者:Looooking  
sync.Mutex是Go標準庫中常用的一個排外鎖,本文主要介紹了Go中sync.Mutex 加鎖失效的問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

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

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

起因

最近在學習 sync.Mutex 加鎖時,寫了下面一段代碼進行練習。

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ù)當中,before update 和 in update 中對應(yīng)結(jié)構(gòu)體的值應(yīng)該是不會變的(畢竟我加了鎖)。然而從運行結(jié)果發(fā)現(xiàn),Update() 函數(shù)執(zhí)行期間,結(jié)構(gòu)體變量的 Value 竟然還是被外部主線程修改了。

分析

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

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

主線程中加上獲取鎖的操作后,會先判斷當前鎖是否被釋放,如果沒被釋放,就會一直進行等待直到鎖釋放后才繼續(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

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

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

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

當然,我們還可以通過緩沖為1的通道實現(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 加鎖失效的問題解決的文章就介紹到這了,更多相關(guān)Go sync.Mutex 加鎖失效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Go多線程中數(shù)據(jù)不一致問題的解決方案(sync鎖機制)

    Go多線程中數(shù)據(jù)不一致問題的解決方案(sync鎖機制)

    在Go語言的并發(fā)編程中,如何確保多個goroutine安全地訪問共享資源是一個關(guān)鍵問題,Go語言提供了sync包,其中包含了多種同步原語,用于解決并發(fā)編程中的同步問題,本文將詳細介紹sync包中的鎖機制,需要的朋友可以參考下
    2024-10-10
  • golang利用函數(shù)閉包實現(xiàn)簡單的中間件

    golang利用函數(shù)閉包實現(xiàn)簡單的中間件

    中間件設(shè)計模式是一種常見的軟件設(shè)計模式,它在許多編程語言和框架中被廣泛應(yīng)用,這篇文章主要為大家介紹一下golang利用函數(shù)閉包實現(xiàn)一個簡單的中間件,感興趣的可以了解下
    2023-10-10
  • Golang巧用defer進行錯誤處理的方法

    Golang巧用defer進行錯誤處理的方法

    錯誤處理是程序的重要組成部分,有效且優(yōu)雅的處理錯誤是大多數(shù)程序員的追求,下面這篇文章主要給大家介紹了關(guān)于Golang中巧用defer進行錯誤處理的方法,文中通過示例介紹的非常詳細,對大家具有一定的參考學習價值,需要的朋友們下面來一起看看吧。
    2017-05-05
  • Go語言反射獲取類型屬性和方法示例

    Go語言反射獲取類型屬性和方法示例

    這篇文章主要為大家介紹了本文將介紹?Go?反射?reflect.StructField?和?reflect.Method?相關(guān)的內(nèi)容,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Go單元測試工具gomonkey的使用

    Go單元測試工具gomonkey的使用

    本文主要介紹了Go單元測試工具gomonkey的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06
  • go使用makefile腳本編譯應(yīng)用的方法小結(jié)

    go使用makefile腳本編譯應(yīng)用的方法小結(jié)

    makefile可以看作是make工具的腳本文件, 而make主要用來處理一系列命令。常用的比如用來編譯和打包文件, 在C/C++的編譯打包中應(yīng)用最廣泛了,這篇文章主要介紹了go使用makefile腳本編譯應(yīng)用,需要的朋友可以參考下
    2022-08-08
  • Go Gin實現(xiàn)文件上傳下載的示例代碼

    Go Gin實現(xiàn)文件上傳下載的示例代碼

    這篇文章主要介紹了Go Gin實現(xiàn)文件上傳下載的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • Golang如何用gorm實現(xiàn)分頁的功能

    Golang如何用gorm實現(xiàn)分頁的功能

    這篇文章主要介紹了Golang如何用gorm實現(xiàn)分頁的功能方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-06-06
  • Go語言簡介和環(huán)境配置

    Go語言簡介和環(huán)境配置

    Go語言保證了既能到達靜態(tài)編譯語言的安全和性能,又達到了動態(tài)語言開發(fā)速度和易維護性,有人形容Go語言:Go=?C?+?Python?,?說明Go語言既有C靜態(tài)語言程序的運行速度,又能達到Python動態(tài)語言的快速開發(fā),這篇文章主要介紹了Go介紹和環(huán)境配置,需要的朋友可以參考下
    2022-07-07
  • golang中有序Map的實現(xiàn)

    golang中有序Map的實現(xiàn)

    Go語言中XContainerOrderedMap庫,解決標準map無序問題,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2025-06-06

最新評論

长汀县| 温宿县| 商洛市| 桑日县| 娱乐| 双辽市| 广河县| 辉南县| 孝义市| 永寿县| 南昌市| 南涧| 普宁市| 蒙自县| 邓州市| 台中县| 乐业县| 敦化市| 申扎县| 夏津县| 长汀县| 固原市| 赫章县| 杭锦旗| 特克斯县| 佛冈县| 绩溪县| 会东县| 焉耆| 霍城县| 方正县| 章丘市| 桑日县| 台北市| 讷河市| 孝感市| 遵义市| 都兰县| 当涂县| 内乡县| 阳信县|