欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語言并發(fā)編程臨界區(qū)的使用

 更新時間:2025年09月26日 09:13:58   作者:Jayden_念舊  
本文主要介紹了Go語言并發(fā)編程臨界區(qū)的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

臨界區(qū)是多線程/并發(fā)編程中的核心概念,指程序中訪問共享資源(如變量、數(shù)據(jù)結(jié)構(gòu)、文件等)的代碼段,這些資源在同一時間只能被一個線程訪問以避免數(shù)據(jù)競爭和不一致。

本篇文章著重介紹臨界區(qū),鎖的詳細(xì)介紹會在下一篇文章中。

基本定義

臨界區(qū)是指:

  • 訪問共享資源的代碼片段
  • 需要同步機(jī)制保護(hù)的部分
  • 同一時間只允許一個執(zhí)行線程/goroutine進(jìn)入的區(qū)域

關(guān)鍵的特性:

  1. 共享資源訪問:涉及對共享內(nèi)存、文件、設(shè)備等資源的讀寫操作
  2. 原子性需求:臨界區(qū)內(nèi)的操作應(yīng)作為一個不可分割的單元執(zhí)行
  3. 互斥/排他訪問:必須確保同一時間只有一個執(zhí)行流能進(jìn)入臨界區(qū)
  4. 有限停留:線程應(yīng)盡快離開臨界區(qū),減少阻塞其他線程的時間

在Go中臨界區(qū)示例

無保護(hù)的臨界區(qū)(危險)

var counter int // 共享變量

func increment() {
    counter++ // 這就是臨界區(qū)(沒有保護(hù))
}

使用Mutex保護(hù)的臨界區(qū)

var (
    counter int
    mu      sync.Mutex
)

func safeIncrement() {
    mu.Lock()         // 進(jìn)入臨界區(qū)前加鎖
    defer mu.Unlock() // 確保退出時解鎖
    
    counter++         // 受保護(hù)的臨界區(qū)
    // 其他操作...
}

臨界區(qū)與鎖的關(guān)系

概念描述
臨界區(qū)需要保護(hù)的代碼段(概念)
保護(hù)臨界區(qū)的實(shí)現(xiàn)機(jī)制(工具)
關(guān)系鎖用來劃定和保護(hù)臨界區(qū),臨界區(qū)是需要鎖保護(hù)的代碼范圍

臨界區(qū)的設(shè)計(jì)規(guī)范

1.最小化原則:

  • 盡量減小臨界區(qū)的范圍
  • 只包含必須同步的操作
   // 不好:包含非必要操作
   mu.Lock()
   data := fetchFromDatabase() // 耗時IO操作
   sharedMap[key] = data
   mu.Unlock()
   
   // 更好:僅保護(hù)共享訪問
   data := fetchFromDatabase()
   mu.Lock()
   sharedMap[key] = data
   mu.Unlock()

2.簡短執(zhí)行

  • 避免在臨界區(qū)內(nèi)執(zhí)行耗時操作如:IO、復(fù)雜計(jì)算
  • 典型臨界區(qū)應(yīng)能在微秒級完成

3.單一職責(zé)

  • 一個臨界去最好只保護(hù)一個共享資源
  • 避免多個不相關(guān)資源共同用同一個鎖

4.無嵌套原則

  • 避免在臨界區(qū)內(nèi)調(diào)用可能獲取其他鎖的方法
  • 防止死鎖發(fā)生

臨界區(qū)保護(hù)機(jī)制對比

1. 互斥鎖(Mutex)

var mu sync.Mutex

func accessShared() {
    mu.Lock()
    // 臨界區(qū)...
    mu.Unlock()
}

2. 讀寫鎖(RWMutex)

var rwMu sync.RWMutex

func readShared() {
    rwMu.RLock()
    // 只讀臨界區(qū)(允許多個讀者)
    rwMu.RUnlock()
}

func writeShared() {
    rwMu.Lock()
    // 寫臨界區(qū)(獨(dú)占)
    rwMu.Unlock()
}

3. 通道(Channel)

var ch = make(chan struct{}, 1) // 容量1的通道模擬鎖

func accessShared() {
    ch <- struct{}{} // 獲取"鎖"
    // 臨界區(qū)...
    <-ch // 釋放"鎖"
}

常會遇到的問題

1. 數(shù)據(jù)競爭(Data Race)

// 兩個goroutine并發(fā)執(zhí)行此函數(shù)會導(dǎo)致數(shù)據(jù)競爭
func race() {
    counter++ // 未保護(hù)的臨界區(qū)
}

檢測:使用go run -racego test -race

2. 死鎖(Deadlock)

func deadlock() {
    mu.Lock()
    mu.Lock() // 重復(fù)加鎖導(dǎo)致死鎖
    mu.Unlock()
    mu.Unlock()
}

3. 活鎖(Livelock)

// 兩個goroutine不斷重試但無法進(jìn)展
func livelock() {
    for {
        if mu.TryLock() { // Go 1.18+
            // 臨界區(qū)...
            mu.Unlock()
            break
        }
        time.Sleep(time.Millisecond) // 可能導(dǎo)致活鎖
    }
}

項(xiàng)目案例改編

銀行賬戶轉(zhuǎn)賬

type Account struct {
    mu      sync.Mutex
    balance int
}

func (a *Account) Transfer(to *Account, amount int) error {
    // 按固定順序加鎖防止死鎖
    first, second := a, to
    if a < to { // 通過地址比較確定順序
        first, second = to, a
    }
    
    first.mu.Lock()
    defer first.mu.Unlock()
    second.mu.Lock()
    defer second.mu.Unlock()
    
    // 臨界區(qū)開始
    if a.balance < amount {
        return errors.New("insufficient balance")
    }
    a.balance -= amount
    to.balance += amount
    // 臨界區(qū)結(jié)束
    
    return nil
}

深度解讀:

  1. func (a *Account) Transfer(to *Account, amount int) error:定義了一個名為Transfer的方法,該方法屬于Account類型的接收者,表示從一個賬戶向另一個賬戶轉(zhuǎn)賬。方法接收兩個參數(shù),to是指向目標(biāo)賬戶的指針,amount是要轉(zhuǎn)賬的金額。返回值是error類型,用于處理可能出現(xiàn)的錯誤情況。
  2. 防止死鎖的機(jī)制:在進(jìn)行轉(zhuǎn)賬操作之前,首先對兩個賬戶進(jìn)行排序(通過比較兩個賬戶指針的內(nèi)存地址),確??偸窍孺i定地址較小的那個賬戶的互斥鎖,然后再鎖定地址較大的那個賬戶的互斥鎖。這種按固定順序加鎖的策略可以有效避免兩個或多個 goroutine 同時嘗試鎖定不同賬戶的互斥鎖時出現(xiàn)的死鎖情況。
  3. 互斥鎖的使用:通過first.mu.Lock()和second.mu.Lock()分別鎖定兩個賬戶的互斥鎖,確保在同一時間只有一個 goroutine 可以訪問這兩個賬戶的余額。defer first.mu.Unlock()和defer second.mu.Unlock()語句用于確保在函數(shù)執(zhí)行完畢后,無論是否發(fā)生錯誤,最終都能釋放這兩個賬戶的互斥鎖。
  4. 臨界區(qū):在兩個賬戶的互斥鎖都被成功鎖定之后,就開始執(zhí)行轉(zhuǎn)賬操作的臨界區(qū)代碼。首先檢查轉(zhuǎn)出賬戶的余額是否足夠覆蓋轉(zhuǎn)賬金額,如果余額不足,則返回一個錯誤信息"insufficient balance"。否則,從轉(zhuǎn)出賬戶扣除相應(yīng)的金額,并將該金額加到轉(zhuǎn)入賬戶的余額中

到此這篇關(guān)于Go語言并發(fā)編程臨界區(qū)的使用的文章就介紹到這了,更多相關(guān)Go語言 臨界區(qū)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • GO Cobra Termui庫開發(fā)終端命令行小工具輕松上手

    GO Cobra Termui庫開發(fā)終端命令行小工具輕松上手

    這篇文章主要為大家介紹了GO語言開發(fā)終端命令行小工具,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • 基于HLS創(chuàng)建Golang視頻流服務(wù)器的優(yōu)缺點(diǎn)

    基于HLS創(chuàng)建Golang視頻流服務(wù)器的優(yōu)缺點(diǎn)

    HLS 是 HTTP Live Streaming 的縮寫,是蘋果開發(fā)的一種基于 HTTP 的自適應(yīng)比特率流媒體傳輸協(xié)議。這篇文章主要介紹了基于 HLS 創(chuàng)建 Golang 視頻流服務(wù)器,需要的朋友可以參考下
    2021-08-08
  • Go語言學(xué)習(xí)之new函數(shù)的用法詳解

    Go語言學(xué)習(xí)之new函數(shù)的用法詳解

    這篇文章主要為大家詳細(xì)介紹了Go語言中new()函數(shù)的相關(guān)知識以及具體用法,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解一下
    2023-05-05
  • go程序測試CPU占用率統(tǒng)計(jì)ps?vs?top兩種不同方式對比

    go程序測試CPU占用率統(tǒng)計(jì)ps?vs?top兩種不同方式對比

    這篇文章主要為大家介紹了go程序測試CPU占用率統(tǒng)計(jì)ps?vs?top兩種不同方式對比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • Golang仿ps實(shí)現(xiàn)獲取Linux進(jìn)程信息

    Golang仿ps實(shí)現(xiàn)獲取Linux進(jìn)程信息

    這篇文章主要為大家學(xué)習(xí)介紹了Golang如何仿ps實(shí)現(xiàn)獲取Linux進(jìn)程信息,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2023-07-07
  • Golang?IOT中的數(shù)據(jù)序列化與解析過程

    Golang?IOT中的數(shù)據(jù)序列化與解析過程

    這篇文章主要介紹了Golang?IOT中的數(shù)據(jù)序列化與解析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • Go實(shí)現(xiàn)socks5服務(wù)器的方法

    Go實(shí)現(xiàn)socks5服務(wù)器的方法

    SOCKS5 是一個代理協(xié)議,它在使用TCP/IP協(xié)議通訊的前端機(jī)器和服務(wù)器機(jī)器之間扮演一個中介角色,使得內(nèi)部網(wǎng)中的前端機(jī)器變得能夠訪問Internet網(wǎng)中的服務(wù)器,或者使通訊更加安全,這篇文章主要介紹了Go實(shí)現(xiàn)socks5服務(wù)器的方法,需要的朋友可以參考下
    2023-07-07
  • Systemd集成Golang二進(jìn)制程序的方法

    Systemd集成Golang二進(jìn)制程序的方法

    這篇文章主要介紹了Systemd集成Golang二進(jìn)制程序的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-10-10
  • Goland IDEA項(xiàng)目多開設(shè)置方式

    Goland IDEA項(xiàng)目多開設(shè)置方式

    這篇文章主要介紹了Goland IDEA項(xiàng)目多開設(shè)置方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 重學(xué)Go語言之錯誤處理與異常機(jī)制詳解

    重學(xué)Go語言之錯誤處理與異常機(jī)制詳解

    Go語言的開發(fā)者顯然覺得?try-catch被濫用了,因此?Go不支持使用?try-catch語句捕獲異常處理,那么,Go語言是如何定義和處理程序的異常呢,下面我們就來看看吧
    2023-08-08

最新評論