成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go 并發(fā)可視化解釋 - sync.Mute

開(kāi)發(fā) 前端
這篇文章通過(guò)生動(dòng)的場(chǎng)景和可視化效果很好地解釋了 Go 語(yǔ)言中 sync.Mutex 的工作原理,以及如何使用互斥鎖來(lái)管理并發(fā)

在學(xué)習(xí) Go 編程語(yǔ)言時(shí),您可能會(huì)遇到這句著名的格言:“不要通過(guò)共享內(nèi)存來(lái)進(jìn)行通信;相反,通過(guò)通信來(lái)共享內(nèi)存。” 這句話構(gòu)成了 Go 強(qiáng)大并發(fā)模型的基礎(chǔ),其中通道(channels)作為協(xié)程之間的主要通信工具。然而,雖然通道是管理并發(fā)的多功能工具,但錯(cuò)誤地假設(shè)我們應(yīng)該始終用通道替換傳統(tǒng)的鎖定機(jī)制,如 Mutex,是一個(gè)錯(cuò)誤的觀念。在某些情況下,使用 Mutex 不僅恰當(dāng),而且比通道更有效。

在我的 Go 并發(fā)可視化系列中,今天我將通過(guò)視覺(jué)方式來(lái)解釋 sync.Mutex。

Golang 基礎(chǔ)

場(chǎng)景

想象一下,有四位 Gopher 自行車(chē)手每天騎車(chē)上班。他們都需要在到達(dá)辦公室后洗個(gè)澡,但辦公室只有一個(gè)浴室。為了防止混亂,他們確保一次只能有一個(gè)人使用浴室。這種獨(dú)占式訪問(wèn)的概念正是 Go Mutex(互斥鎖)的核心。

每天早上在辦公室洗澡對(duì)自行車(chē)手和跑步者來(lái)說(shuō)是一個(gè)小小的競(jìng)爭(zhēng)。

普通模式

今天最早到達(dá)的是 Stringer。當(dāng)他來(lái)的時(shí)候,沒(méi)有人在使用浴室,因此他可以立即使用浴室。

對(duì)一個(gè)未加鎖的 Mutex 調(diào)用 Lock() 會(huì)立即成功。

片刻后,Partier 到了。Partier 發(fā)現(xiàn)有人在使用浴室,但他不知道是誰(shuí),也不知道什么時(shí)候會(huì)結(jié)束使用。此時(shí),他有兩個(gè)選擇:站在浴室前面(主動(dòng)等待),或者離開(kāi)并稍后再回來(lái)(被動(dòng)等待)。按 Go 的術(shù)語(yǔ),前者被稱(chēng)為“自旋”(spinning)。自旋的協(xié)程會(huì)占用 CPU 資源,增加了在鎖定可用時(shí)獲取 Mutex 的機(jī)會(huì),而無(wú)需進(jìn)行昂貴的上下文切換。然而,如果 Mutex 不太可能很快可用,繼續(xù)占用 CPU 資源會(huì)降低其他協(xié)程獲取 CPU 時(shí)間的機(jī)會(huì)。

從版本 1.21 開(kāi)始,Golang 允許到達(dá)的協(xié)程自旋一段時(shí)間。如果在指定時(shí)間內(nèi)無(wú)法獲取 Mutex,它將進(jìn)入休眠狀態(tài),以便其他協(xié)程有機(jī)會(huì)運(yùn)行。

到達(dá)的協(xié)程首先自旋,然后休眠。

Candier 到了。就像 Partier 一樣,她試圖獲取浴室。

 

因?yàn)樗齽偟剑绻?Stringer 很快釋放浴室,她就有很大的機(jī)會(huì)在被動(dòng)等待之前獲取它。這被稱(chēng)為普通模式。

普通模式的性能要好得多,因?yàn)閰f(xié)程可以連續(xù)多次獲取 Mutex,即使有阻塞的等待者。

1*GJ7OW0_8z_8QjXPa2cFxPw.png

go/src/sync/mutex.go at go1.21.0 · golang/go · GitHub[1]

新到達(dá)的協(xié)程在爭(zhēng)奪所有權(quán)時(shí)具有優(yōu)勢(shì)。

饑餓模式

Partier 回來(lái)了。由于他等待的時(shí)間很長(zhǎng)(超過(guò) 1 毫秒),他將嘗試以饑餓模式獲取浴室。當(dāng) Swimmer 來(lái)時(shí),他注意到有人餓了,他不會(huì)嘗試獲取浴室,也不會(huì)自旋。相反,他會(huì)排隊(duì)在等待隊(duì)列的尾部。

在這種饑餓模式下,當(dāng) Candier 結(jié)束時(shí),她會(huì)直接把浴室交給 Partier。此時(shí)沒(méi)有競(jìng)爭(zhēng)。

饑餓模式是防止尾延遲的病理情況的重要措施。

Partier 完成了他的回合并釋放了浴室。此時(shí),只有 Swimmer 在等待,因此他將立即擁有它。Swimmer 如果發(fā)現(xiàn)自己是最后一個(gè)等待的人,他會(huì)將 Mutex 設(shè)置回普通模式。如果他發(fā)現(xiàn)自己的等待時(shí)間少于 1 毫秒,也會(huì)這樣做。

最后,Swimmer 在使用浴室后釋放了它。請(qǐng)注意,Mutex 不會(huì)將所有者從“已鎖定(由 Goroutine A 鎖定)”狀態(tài)更改為“已鎖定(由 Goroutine B 鎖定)”狀態(tài)。它始終會(huì)在“已鎖定”到“未鎖定”然后再到“已鎖定”的狀態(tài)之間切換。出于簡(jiǎn)潔起見(jiàn),上面的圖像中省略了中間狀態(tài)。

展示代碼!

Mutex 的實(shí)現(xiàn)隨時(shí)間而變化,實(shí)際上,要完全理解它的實(shí)現(xiàn)并不容易。幸運(yùn)的是,我們不必完全理解其實(shí)現(xiàn)就能高效使用它。如果從這篇博客中只能記住一件事,那一定是:早到的人不一定贏得比賽。相反,新到達(dá)的協(xié)程通常具有更高的機(jī)會(huì),因?yàn)樗鼈內(nèi)栽?CPU 上運(yùn)行。Golang 還嘗試避免通過(guò)實(shí)現(xiàn)饑餓模式來(lái)使等待者被餓死。

package main

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

func main() {
    wg := sync.WaitGroup{}
    wg.Add(4)
    bathroom := sync.Mutex{}

    takeAShower := func(name string) {
        defer wg.Done()
        fmt.Printf("%s: I want to take a shower. I'm trying to acquire the bathroom\n", name)
        bathroom.Lock()
        fmt.Printf("%s: I have the bathroom now, taking a shower\n", name)
        time.Sleep(500 * time.Microsecond)
        fmt.Printf("%s: I'm done, I'm unlocking the bathroom\n", name)
        bathroom.Unlock()
    }

    go takeAShower("Partier")
    go takeAShower("Candier")
    go takeAShower("Stringer")
    go takeAShower("Swimmer")

    wg.Wait()
    fmt.Println("main: Everyone is Done. Shutting down...")
}

正如您可能猜到的,并發(fā)代碼的結(jié)果幾乎總是非確定性的。

第一次

Swimmer: I want to take a shower. I'm trying to acquire the bathroom

Partier: I want to take a shower. I'm trying to acquire the bathroom

Candier: I want to take a shower. I'm trying to acquire the bathroom

Stringer: I want to take a shower. I'm trying to acquire the bathroom

Swimmer: I have the bathroom now, taking a shower

Swimmer: I'm done, I'm unlocking the bathroom

Partier: I have the bathroom now, taking a shower

Partier: I'm done, I'm unlocking the bathroom

Candier: I have the bathroom now, taking a shower

Candier: I'm done, I'm unlocking the bathroom

Stringer: I have the bathroom now, taking a shower

Stringer: I'm done, I'm unlocking the bathroom

main: Everyone is Done. Shutting down...

第二次

Swimmer: I want to take a shower. I'm trying to acquire the bathroom

Swimmer: I have the bathroom now, taking a shower

Partier: I want to take a shower. I'm trying to acquire the bathroom

Stringer: I want to take a shower. I'm trying to acquire the bathroom

Candier: I want to take a shower. I'm trying to acquire the bathroom

Swimmer: I'm done, I'm unlocking the bathroom

Partier: I have the bathroom now, taking a shower

Partier: I'm done, I'm unlocking the bathroom

Stringer: I have the bathroom now, taking a shower

Stringer: I'm done, I'm unlocking the bathroom

Candier: I have the bathroom now, taking a shower

Candier: I'm done, I'm unlocking the bathroom

main: Everyone is Done. Shutting down...

自己實(shí)現(xiàn) Mutex

實(shí)現(xiàn) sync.Mutex 是困難的,但使用具有緩沖的通道來(lái)實(shí)現(xiàn) Mutex 卻相當(dāng)容易。

type MyMutex struct {
    ch chan bool
}

func NewMyMutex() *MyMutex {
    return &MyMutex{
        // 緩沖大小必須為 1
        ch: make(chan bool, 1),
    }
}

// Lock 鎖定 m。
// 如果鎖已被使用,調(diào)用的協(xié)程將被阻塞,直到 Mutex 可用。
func (m *MyMutex) Lock() {
    [m.ch](http://m.ch) <- true
}

// Unlock 解鎖 m。
func (m *MyMutex) Unlock() {
    <-m.ch
}

這篇文章通過(guò)生動(dòng)的場(chǎng)景和可視化效果很好地解釋了 Go 語(yǔ)言中 sync.Mutex 的工作原理,以及如何使用互斥鎖來(lái)管理并發(fā)

責(zé)任編輯:趙寧寧 來(lái)源: 小技術(shù)君
相關(guān)推薦

2023-10-20 13:35:19

GoWaitGroup

2023-10-06 23:31:25

可視化Go

2023-09-15 11:32:18

selectGo可視化解釋

2023-09-11 10:17:20

Go編程語(yǔ)言

2017-11-10 11:27:48

Go并行算法

2021-01-28 10:55:31

算法可視化數(shù)據(jù)

2020-07-01 09:08:55

神經(jīng)網(wǎng)絡(luò)深度學(xué)習(xí)網(wǎng)絡(luò)

2017-12-26 14:05:21

潤(rùn)乾大屏可視化

2021-09-30 09:21:28

Go語(yǔ)言并發(fā)編程

2024-10-14 08:51:52

協(xié)程Go語(yǔ)言

2024-08-12 10:52:00

AI模型

2020-03-11 14:39:26

數(shù)據(jù)可視化地圖可視化地理信息

2011-07-02 14:12:00

2011-07-11 22:22:38

2022-08-15 08:02:09

Go程序函數(shù)

2017-10-14 13:54:26

數(shù)據(jù)可視化數(shù)據(jù)信息可視化

2009-04-21 14:26:41

可視化監(jiān)控IT管理摩卡

2022-08-26 09:15:58

Python可視化plotly

2020-08-21 16:08:18

NVIDIA

2023-12-25 09:58:25

sync包Go編程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 成人午夜电影在线观看 | 日韩三级在线观看 | 欧美视频一区二区三区 | 欧美福利一区 | 草久久久| 久草热在线 | 久久91精品国产一区二区 | 亚洲精品久久久久国产 | 欧美日韩一区二区三区四区 | 久久精品成人 | 日韩欧美在线视频观看 | 久久久久免费 | 午夜理伦三级理论三级在线观看 | 久久精品国产免费一区二区三区 | 国产精品日韩欧美一区二区三区 | 久久久久久久久久久福利观看 | 精品一区二区久久久久久久网精 | 亚洲精品白浆高清久久久久久 | 在线日韩| 国产高清免费 | www.99热.com| 亚洲成人精品在线观看 | 欧美一区二区成人 | 成人三级网址 | 人人人艹 | 日韩在线国产精品 | 一区二区三区免费 | 黄色大片在线视频 | 日本一区二区在线视频 | 国产操操操 | 欧美日韩视频在线 | 亚洲精品一区二区三区蜜桃久 | 国产精品久久久久久久久久久久冷 | 91亚洲精品在线 | 男女羞羞视频网站 | 亚洲高清视频在线观看 | 欧美日本一区二区 | 久久精品在线 | 99精品国产一区二区青青牛奶 | 黄色大片在线免费观看 | 一区二区三区国产精品 |