<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Lock/Unlock 沒有成對出現,就可能會出現死鎖或者是因為Unlock一個未加鎖的Mutex而導致 panic。
忘記Unlock的情形
忘記Lock的情形一般是誤刪除了或者註釋掉了Lock。
eg:
func main() { var mu sync.Mutex defer mu.Unlock() fmt.Println("oh, missing Lock!") }
error result:
實際上sync包下的同步原語在使用後都是不可複製的,原因在於Mutex是有狀態的,其state的值時刻在變化,如果複製一個已經加鎖的Metux物件給一個新的變數,可能這個變數剛初始化就顯示被加鎖了,這顯然是不合理的。
eg:以下程式碼在呼叫 foo 函數的時候,呼叫者會複製 Mutex 變數 c 作為 foo 函數的引數,不幸的是,複製之前已經使用了這個鎖,這就導致,複製的 Counter 是一個帶狀態 Counter,從而會導致死鎖。
type Counter struct { sync.Mutex Count int } func main() { var c Counter c.Lock() defer c.Unlock() c.Count++ foo(c) // 複製鎖 } // 這裡Counter的引數是通過複製的方式傳入的 func foo(c Counter) { c.Lock() defer c.Unlock() fmt.Println("in foo") }
error result:還好有Go的協程死鎖檢查機制,程式執行後會快速失敗而不是一直hang住。
Go Vet指令
我們當然不想程式執行了才發現死鎖,我們可以通過go vet指令來在執行前檢查我們的程式碼是否存在lock copy問題:
檢查原理
檢查是通過copylock分析器靜態分析實現的。這個分析器會分析函數呼叫、range 遍歷、複製、宣告、函數返回值等位置,有沒有鎖的值 copy 的情景,以此來判斷有沒有問題。
通過原始碼我們可以看到實現了Lock或者Unlock介面的struct都支援copylock檢查。
var lockerType *types.Interface // Construct a sync.Locker interface type. func init() { nullary := types.NewSignature(nil, nil, nil, false) // func() methods := []*types.Func{ types.NewFunc(token.NoPos, nil, "Lock", nullary), types.NewFunc(token.NoPos, nil, "Unlock", nullary), } lockerType = types.NewInterface(methods, nil).Complete() }
Mutex不像Java中的ReentrantLock擁有可重入的功能,主要是因為其實現中沒有標記位記錄哪個goroutine 擁有這把鎖,所以Mutex是一個不可重入鎖,而一旦誤用Mutex的重入就會報錯。
eg:
func foo(l sync.Locker) { fmt.Println("in foo") l.Lock() bar(l) l.Unlock() } func bar(l sync.Locker) { l.Lock() fmt.Println("in bar") l.Unlock() } func main() { l := &sync.Mutex{} foo(l) }
error result:我們可以看到當在bar方法中嘗試再次獲取鎖時,獲取不到,觸發了死鎖。
兩個或兩個以上的程序(或執行緒,goroutine)
執行過程中,因爭奪共用資源而處於一種互相等待的狀態,如果沒有外部干涉,它們都將無法推進下去,此時,我們稱系統處於死鎖狀態或系統產生了死鎖。
死鎖產生的4個必要條件
如果想避免死鎖,我們只要思考如何打破以下任意條件就可以。
資源,P2 等待 P3 持有的資源,依此類推,最後是 PN 等待 P1 持有的資源,這就形成
了一個環路等待的死結。
eg:在這裡我們以辦理居住證業務,舉一個簡單的環路等待導致死鎖的例子:
//辦理居住證 func main() { // 網籤中心證明 var psCertificate sync.Mutex // 社群證明 var propertyCertificate sync.Mutex var wg sync.WaitGroup wg.Add(2) // 需要網籤中心和社群都處理 // 網籤中心處理goroutine go func() { defer wg.Done() // 網籤中心處理完成 psCertificate.Lock() defer psCertificate.Unlock() // 檢查材料 time.Sleep(5 * time.Second) // 請求社群的證明 propertyCertificate.Lock() propertyCertificate.Unlock() }() // 社群處理goroutine go func() { defer wg.Done() // 社群處理完成 propertyCertificate.Lock() defer propertyCertificate.Unlock() // 檢查材料 time.Sleep(5 * time.Second) // 請求網籤中心的證明 psCertificate.Lock() psCertificate.Unlock() }() wg.Wait() fmt.Println("成功完成") }
error result:
1.可以引入一個第三方的鎖,大家都依賴這個鎖進行業務處理,比如現在政府推行的一站式政務服務中心。
2.解決持有等待問題,比如社群不需要看到網籤中心的證明才給開居住證明。
以上就是Go並行同步Mutex典型易錯使用場景的詳細內容,更多關於Go Mutex易錯場景的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45