91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go中sync包Cond使用場景是什么

發布時間:2023-03-07 17:44:34 來源:億速云 閱讀:92 作者:iii 欄目:開發技術

本篇內容介紹了“Go中sync包Cond使用場景是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

    背景

    編寫代碼過程中, 通常有主協程和多個子協程進行協作的過程,比如通過 WaitGroup 可以實現當所有子協程完成之后, 主協程再繼續執行。

    如上的場景是主協程等待子協程達到某個狀態再繼續運行。 但是反過來怎么操作呢,要求一組子協程等待主協達到某個狀態時才繼續運行。這個時候就需要用到 Cond 了

    Cond 簡介

    Cond 是和某個條件相關,在條件還沒有滿足的時候,所有等待這個條件的協程都會被阻塞住,只有這個條件滿足的時候,等待的協程才可能繼續進行下去。
    Cond 在初始化的時候,需要關聯一個 Locker 接口的實例,一般會使用 Mutex 或者 RWMutex。
    Cond 關聯的 Locker 實例可以通過 c.L 訪問,它內部維護著一個先入先出的等待隊列。
    Cond 分別有三個方法

    • Wait

    會把當前協程放入Cond的等待隊列中并阻塞,直到被Signal或者Broadcast方法從等待隊列中移除并喚醒,用于子協程阻塞。

    • Signal

    主協程喚醒等待隊列中的一個子協程,先喚醒最先阻塞的子協程,被喚醒的子協程繼續執行。

    • Broadcast

    主協程喚醒等待隊列中的全部協程,所有子協程繼續執行。

    注意:調用Signal和Broadcast方法,不強求持有c.L的鎖,調用Wait方法是必須要持有c.L的鎖。

    使用示例

    Signal的使用場景

    大家都去醫院先排隊,然后等待叫號,先排隊的先叫號。這次模擬有5個病人,分別先排隊。 然后護士根據排隊先后來叫號;
    具體場景是,5個病人在三秒中之內分別排號,護士今天要叫5個號,一秒叫一個,叫完5個號就結束了
    代碼如下:

    package main
    import (
    	"fmt"
    	"math/rand"
    	"sync"
    	"time"
    )
    
    func main() {
    	c := sync.NewCond(&sync.Mutex{})
    	num := 0
    	// 當前叫號是幾號
    	hand_num := 0
    	for i := 0; i < 5; i++ {
    		go func(i int) {
    			// 分別在不同時間排隊
    			time.Sleep(time.Second * time.Duration(rand.Int63n(10)))
    			c.L.Lock()
    			num++
    			// 當前取得號。
    			cur := num
    			fmt.Printf("%s  %d 號病人取到了 %d 號\n", time.Now().Format("2006-01-02 15:04:05"), i, cur)
    			// 取到號了,等待叫號
    			c.Wait()
    			fmt.Printf("%s  %d 號病人排隊號是 %d 號,被叫號了\n", time.Now().Format("2006-01-02 15:04:05"), i, cur)
    			hand_num = cur
    			c.L.Unlock()
    		}(i)
    	}
    
    	// 都叫號了
    	for hand_num != 5 {
    		// 叫號
    		c.Signal()
    		time.Sleep(time.Second * 1)
    	}
    
    	time.Sleep(time.Second * 10)
    }

    執行結果如下

    Go中sync包Cond使用場景是什么

    結果表明,5個病人,分別在三秒鐘內先后取號, 然后護士每過一秒鐘按照排隊的先后順序叫一個號(叫號的過程依然有病人取號),先取號的被先叫號。
    此場景中,5個病人相當于5個協程, 主協程反復使用Signal() 按照順序一個個喚醒阻塞的子協程。

    Broadcast的使用場景

    場景為如下: 運動員跑步比賽,要求8秒內全部運動員準備好,然后等待教練發令, 教練10秒后發令,所有運動員在發令后開始跑。

    package main
    
    import (
    	"fmt"
    	"math/rand"
    	"sync"
    	"time"
    )
    
    func main() {
    	c := sync.NewCond(&sync.Mutex{})
    
    	for i := 0; i < 10; i++ {
    		go func(i int) {
    			// 隨機一個8秒內的準備時間
    			time.Sleep(time.Second * time.Duration(rand.Int63n(8)))
    			fmt.Printf("%s 運動員%d已準備就緒\n", time.Now().Format("2006-01-02 15:04:05"), i)
    			c.L.Lock()
    			// 準備完畢,等待教練發令
    			c.Wait()
    			c.L.Unlock()
    			fmt.Printf("%s 運動員%d開跑\n", time.Now().Format("2006-01-02 15:04:05"), i)
    		}(i)
    	}
    
    	// 主協程等待10秒后發令
    	time.Sleep(time.Second * 10)
    	fmt.Printf("%s 教練發令。\n", time.Now().Format("2006-01-02 15:04:05"))
    	// 教練發令。通知所有運動員開始跑步, 即喚起之前 wait()的所有協程
    	c.Broadcast()
    	// 等待跑步
    	time.Sleep(time.Second * 5)
    }

    執行結果如下:

    Go中sync包Cond使用場景是什么

    如結果所示, 10個運動員在8秒內分別準備好,等待教練發令后,同時開跑。
    此場景中,10個運動員相當于10個協程, 同時等待主協程的命令,使用Broadcast() 喚醒所有阻塞的子協程。

    注意事項

    使用 Cond,最容易踩的坑就是調用 Wait() 方法之前,調用者沒有持有鎖或沒有檢查輔助條件。
    在如上示例代碼中,假如把調用 Wait() 方法前后的加鎖和釋放鎖的代碼注釋掉,運行代碼會導致程序 panic。原因是調用 Wait 方法,會先把調用者放入等待隊列中,然后釋放鎖。此時如果在未持有鎖時調用釋放鎖的方法,就會導致程序 panic。

    “Go中sync包Cond使用場景是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    武定县| 化隆| 宽城| 河南省| SHOW| 芒康县| 田东县| 华安县| 根河市| 金阳县| 南京市| 本溪| 英超| 双流县| 崇州市| 丹凤县| 修武县| 丘北县| 高邑县| 泸水县| 沾化县| 抚松县| 阿克| 江达县| 四子王旗| 汝阳县| 西宁市| 普兰县| 郯城县| 乡宁县| 苗栗县| 辽阳市| 辽宁省| 青海省| 上栗县| 青龙| 浏阳市| 东丽区| 凤冈县| 福建省| 维西|