首頁  >  文章  >  後端開發  >  聊聊golang中的Barrier(屏障)

聊聊golang中的Barrier(屏障)

PHPz
PHPz原創
2023-04-11 09:10:37882瀏覽

在編寫並發程式碼時,經常需要保證多個goroutine之間的同步和相互之間的令牌或鎖,以防止資料競爭和競態條件。 Go語言透過chan和sync套件提供了一些機制來實現這些同步,但有時候並不夠靈活,需要一些更高階的同步方法,這時候就需要用到屏障。

屏障是一種同步原語,它用於等待一組goroutine在同一時刻完成某項操作,然後再繼續執行下一步操作,這是一種非常常見的同步機制。在Golang中也提供了實現屏障的機制,即「Barrier(屏障)」。

屏障的原理是將一組goroutine分為兩個階段,第一階段在每個goroutine執行完自己的任務後停止,並等待其他goroutine完成,第二階段,當所有goroutine都已停止並互相設定訊號時,所有goroutine都同時恢復執行。

Golang在sync套件中提供了「WaitGroup」類型,使用Add方法來添加等待的goroutine數量,Done方法用於每個goroutine完成任務後向WaitGroup減少一個計數器,最後,Wait方法阻塞,直到計數器降為零,即所有goroutine都已完成任務,才會繼續執行下一步操作。

但是,WaitGroup有一個缺點,它只能等待一組固定數量的goroutine完成,當有新的goroutine加入時,我們就無法使用它了。這時候,我們可以使用Barrier來解決這個問題。

Barrier可以用於任意數量的goroutine,並且可以在每個階段結束時執行任意指定的操作。它包含一個計數器,表示有多少個goroutine正在等待該群組操作完成,以及一個函數,用於在每個階段結束時執行。

Golang中的“一組等待線程”,可以使用sync包的“WaitGroup(等待組)”來實現:

var wg sync.WaitGroup

func worker() {
    defer wg.Done()
    // 执行自己的任务
}

func main() {
    for i := 0; i < n; i++ {
        wg.Add(1)
        go worker()
    }
    // 等待所有线程完成
    wg.Wait()
}

現在,我們使用“Barrier”,創建一個可以應用於變化的goroutine的範例:

package main

import "fmt"
import "sync"

func main() {
    b := sync.NewCond(&sync.Mutex{})
    done := make(chan bool)

    worker := func(id int) {
        defer func() {
            fmt.Printf("Worker %d done\n", id)
            done <- true
        }()
        fmt.Printf("Worker %d processing\n", id)
        b.L.Lock()
        b.Wait() // 等待阻塞直到b.Broadcast()被执行
        b.L.Unlock()
        fmt.Printf("Worker %d resumed\n", id)
    }

    go func() {
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go worker(i)
        }
    }()

    go func() {
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go worker(i)
        }
    }()

    go func() {
        wg.Wait()
        b.Broadcast()
    }()

    for i := 0; i < 20; i++ {
        <-done
    }
    fmt.Printf("All workers done\n")
}

這個範例創建了20個goroutine,分別分為兩個階段,第一階段在每個goroutine完成自己的任務後等待,第二階段等待所有goroutine都完成後再執行操作。

當兩組goroutine被創建後,其中一個goroutine調用了「Wait」並阻塞,直到所有goroutine完成任務。使得其他執行緒都完成任務時,才釋放阻塞,並透過使用「Broadcast」向所有goroutine發送訊號,以繼續執行下一步操作。

總之,Golang的Barrier允許您更高級地同步並發操作,並使您的程式碼更健壯、可靠性更高。

以上是聊聊golang中的Barrier(屏障)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn