最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言無緩沖的通道的使用

 更新時間:2024年01月05日 09:46:06   作者:C語言中文網(wǎng)  
Go語言中無緩沖的通道是指在接收前沒有能力保存任何值的通道,本文主要介紹了Go語言無緩沖的通道的使用,具有一定的參考價值,感興趣的可以了解一下

Go語言中無緩沖的通道(unbuffered channel)是指在接收前沒有能力保存任何值的通道。這種類型的通道要求發(fā)送 goroutine 和接收 goroutine 同時準備好,才能完成發(fā)送和接收操作。

如果兩個 goroutine 沒有同時準備好,通道會導致先執(zhí)行發(fā)送或接收操作的 goroutine 阻塞等待。這種對通道進行發(fā)送和接收的交互行為本身就是同步的。其中任意一個操作都無法離開另一個操作單獨存在。

阻塞指的是由于某種原因數(shù)據(jù)沒有到達,當前協(xié)程(線程)持續(xù)處于等待狀態(tài),直到條件滿足才解除阻塞。

同步指的是在兩個或多個協(xié)程(線程)之間,保持數(shù)據(jù)內容一致性的機制。

下圖展示兩個 goroutine 如何利用無緩沖的通道來共享一個值。

使用無緩沖的通道在 goroutine 之間同步

圖:使用無緩沖的通道在 goroutine 之間同步

在第 1 步,兩個 goroutine 都到達通道,但哪個都沒有開始執(zhí)行發(fā)送或者接收。在第 2 步,左側的 goroutine 將它的手伸進了通道,這模擬了向通道發(fā)送數(shù)據(jù)的行為。這時,這個 goroutine 會在通道中被鎖住,直到交換完成。

在第 3 步,右側的 goroutine 將它的手放入通道,這模擬了從通道里接收數(shù)據(jù)。這個 goroutine 一樣也會在通道中被鎖住,直到交換完成。在第 4 步和第 5 步,進行交換,并最終在第 6 步,兩個 goroutine 都將它們的手從通道里拿出來,這模擬了被鎖住的 goroutine 得到釋放。兩個 goroutine 現(xiàn)在都可以去做別的事情了。

為了講得更清楚,讓我們來看兩個完整的例子。這兩個例子都會使用無緩沖的通道在兩個 goroutine 之間同步交換數(shù)據(jù)。

【示例 1】在網(wǎng)球比賽中,兩位選手會把球在兩個人之間來回傳遞。選手總是處在以下兩種狀態(tài)之一,要么在等待接球,要么將球打向對方??梢允褂脙蓚€ goroutine 來模擬網(wǎng)球比賽,并使用無緩沖的通道來模擬球的來回,代碼如下所示。

// 這個示例程序展示如何用無緩沖的通道來模擬
// 2 個goroutine 間的網(wǎng)球比賽
package main
import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)
// wg 用來等待程序結束
var wg sync.WaitGroup
func init() {
    rand.Seed(time.Now().UnixNano())
}
// main 是所有Go 程序的入口
func main() {
    // 創(chuàng)建一個無緩沖的通道
    court := make(chan int)
    // 計數(shù)加 2,表示要等待兩個goroutine
    wg.Add(2)
    // 啟動兩個選手
    go player("Nadal", court)
    go player("Djokovic", court)
    // 發(fā)球
    court <- 1
    // 等待游戲結束
    wg.Wait()
}
// player 模擬一個選手在打網(wǎng)球
func player(name string, court chan int) {
    // 在函數(shù)退出時調用Done 來通知main 函數(shù)工作已經(jīng)完成
    defer wg.Done()
    for {
        // 等待球被擊打過來
        ball, ok := <-court
        if !ok {
            // 如果通道被關閉,我們就贏了
            fmt.Printf("Player %s Won\n", name)
            return
        }
        // 選隨機數(shù),然后用這個數(shù)來判斷我們是否丟球
        n := rand.Intn(100)
        if n%13 == 0 {
            fmt.Printf("Player %s Missed\n", name)
            // 關閉通道,表示我們輸了
            close(court)
            return
        }
        // 顯示擊球數(shù),并將擊球數(shù)加1
        fmt.Printf("Player %s Hit %d\n", name, ball)
        ball++
        // 將球打向對手
        court <- ball
    }
}

運行這個程序,輸出結果如下所示。

Player Nadal Hit 1
Player Djokovic Hit 2
Player Nadal Hit 3
Player Djokovic Missed
Player Nadal Won

代碼說明如下:

  • 第 22 行,創(chuàng)建了一個 int 類型的無緩沖的通道,讓兩個 goroutine 在擊球時能夠互相同步。
  • 第 28 行和第 29 行,創(chuàng)建了參與比賽的兩個 goroutine。在這個時候,兩個 goroutine 都阻塞住等待擊球。
  • 第 32 行,將球發(fā)到通道里,程序開始執(zhí)行這個比賽,直到某個 goroutine 輸?shù)舯荣悺?/li>
  • 第 43 行可以找到一個無限循環(huán)的 for 語句。在這個循環(huán)里,是玩游戲的過程。
  • 第 45 行,goroutine 從通道接收數(shù)據(jù),用來表示等待接球。這個接收動作會鎖住 goroutine,直到有數(shù)據(jù)發(fā)送到通道里。通道的接收動作返回時。
  • 第 46 行會檢測 ok 標志是否為 false。如果這個值是 false,表示通道已經(jīng)被關閉,游戲結束。
  • 第 53 行到第 60 行,會產(chǎn)生一個隨機數(shù),用來決定 goroutine 是否擊中了球。
  • 第 58 行如果某個 goroutine 沒有打中球,關閉通道。之后兩個 goroutine 都會返回,通過 defer 聲明的 Done 會被執(zhí)行,程序終止。
  • 第 64 行,如果擊中了球 ball 的值會遞增 1,并在第 67 行,將 ball 作為球重新放入通道,發(fā)送給另一位選手。在這個時刻,兩個 goroutine 都會被鎖住,直到交換完成。

【示例 2】用不同的模式,使用無緩沖的通道,在 goroutine 之間同步數(shù)據(jù),來模擬接力比賽。在接力比賽里,4 個跑步者圍繞賽道輪流跑。第二個、第三個和第四個跑步者要接到前一位跑步者的接力棒后才能起跑。比賽中最重要的部分是要傳遞接力棒,要求同步傳遞。在同步接力棒的時候,參與接力的兩個跑步者必須在同一時刻準備好交接。代碼如下所示。

// 這個示例程序展示如何用無緩沖的通道來模擬
// 4 個goroutine 間的接力比賽
package main
import (
    "fmt"
    "sync"
    "time"
)
// wg 用來等待程序結束
var wg sync.WaitGroup
// main 是所有Go 程序的入口
func main() {
    // 創(chuàng)建一個無緩沖的通道
    baton := make(chan int)
    // 為最后一位跑步者將計數(shù)加1
    wg.Add(1)
    // 第一位跑步者持有接力棒
    go Runner(baton)
    // 開始比賽
    baton <- 1
    // 等待比賽結束
    wg.Wait()
}
// Runner 模擬接力比賽中的一位跑步者
func Runner(baton chan int) {
    var newRunner int
    // 等待接力棒
    runner := <-baton
    // 開始繞著跑道跑步
    fmt.Printf("Runner %d Running With Baton\n", runner)
    // 創(chuàng)建下一位跑步者
    if runner != 4 {
        newRunner = runner + 1
        fmt.Printf("Runner %d To The Line\n", newRunner)
        go Runner(baton)
    }
    // 圍繞跑道跑
    time.Sleep(100 * time.Millisecond)
    // 比賽結束了嗎?
    if runner == 4 {
        fmt.Printf("Runner %d Finished, Race Over\n", runner)
        wg.Done()
        return
    }
    // 將接力棒交給下一位跑步者
    fmt.Printf("Runner %d Exchange With Runner %d\n",
        runner,
        newRunner)
    baton <- newRunner
}

運行這個程序,輸出結果如下所示。

Runner 1 Running With Baton
Runner 1 To The Line
Runner 1 Exchange With Runner 2
Runner 2 Running With Baton
Runner 2 To The Line
Runner 2 Exchange With Runner 3
Runner 3 Running With Baton
Runner 3 To The Line
Runner 3 Exchange With Runner 4
Runner 4 Running With Baton
Runner 4 Finished, Race Over

代碼說明如下:

  • 第 17 行,創(chuàng)建了一個無緩沖的 int 類型的通道 baton,用來同步傳遞接力棒。
  • 第 20 行,我們給 WaitGroup 加 1,這樣 main 函數(shù)就會等最后一位跑步者跑步結束。
  • 第 23 行創(chuàng)建了一個 goroutine,用來表示第一位跑步者來到跑道。
  • 第 26 行,將接力棒交給這個跑步者,比賽開始。
  • 第 29 行,main 函數(shù)阻塞在 WaitGroup,等候最后一位跑步者完成比賽。
  • 第 37 行,goroutine 對 baton 通道執(zhí)行接收操作,表示等候接力棒。
  • 第 46 行,一旦接力棒傳了進來,就會創(chuàng)建一位新跑步者,準備接力下一棒,直到 goroutine 是第四個跑步者。
  • 第 50 行,跑步者圍繞跑道跑 100 ms。
  • 第 55 行,如果第四個跑步者完成了比賽,就調用 Done,將 WaitGroup 減 1,之后 goroutine 返回。
  • 第 64 行,如果這個 goroutine 不是第四個跑步者,接力棒會交到下一個已經(jīng)在等待的跑步者手上。在這個時候,goroutine 會被鎖住,直到交接完成。

在這兩個例子里,我們使用無緩沖的通道同步 goroutine,模擬了網(wǎng)球和接力賽。代碼的流程與這兩個活動在真實世界中的流程完全一樣,這樣的代碼很容易讀懂。

現(xiàn)在知道了無緩沖的通道是如何工作的,下一節(jié)我們將為大家介紹帶緩沖的通道。

到此這篇關于Go語言無緩沖的通道的使用的文章就介紹到這了,更多相關Go 無緩沖通道內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • go語言實現(xiàn)十大常見的排序算法示例

    go語言實現(xiàn)十大常見的排序算法示例

    這篇文章主要為大家介紹了go語言實現(xiàn)十大常見的排序算法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • Go語言實現(xiàn)棧與隊列基本操作學家

    Go語言實現(xiàn)棧與隊列基本操作學家

    go語言中,并沒有棧與隊列相關的數(shù)據(jù)結構,但是我們可以借助切片來實現(xiàn)棧與隊列的操作;接下來我們一起實現(xiàn)棧與隊列基本操作,感興趣的可以了解一下
    2022-11-11
  • golang版本升級如何實現(xiàn)

    golang版本升級如何實現(xiàn)

    這篇文章主要介紹了golang版本升級如何實現(xiàn)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-07-07
  • go動態(tài)限制并發(fā)數(shù)量的實現(xiàn)示例

    go動態(tài)限制并發(fā)數(shù)量的實現(xiàn)示例

    本文主要介紹了Go并發(fā)控制方法,通過帶緩沖通道和第三方庫實現(xiàn)并發(fā)數(shù)量限制,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-07-07
  • Go語言pointer及switch?fallthrough實戰(zhàn)詳解

    Go語言pointer及switch?fallthrough實戰(zhàn)詳解

    這篇文章主要為大家介紹了Go語言pointer及switch?fallthrough實戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Goland使用delve進行遠程調試的詳細教程

    Goland使用delve進行遠程調試的詳細教程

    網(wǎng)上給出的使用delve進行遠程調試,都需要先在本地交叉編譯或者在遠程主機上編譯出可運行的程序,然后再用delve在遠程啟動程序,本教程會將上面的步驟簡化為只需要兩步,1,在遠程運行程序2,在本地啟動調試,需要的朋友可以參考下
    2024-08-08
  • Go 數(shù)據(jù)結構之堆排序示例詳解

    Go 數(shù)據(jù)結構之堆排序示例詳解

    這篇文章主要為大家介紹了Go 數(shù)據(jù)結構之堆排序示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Golang timer可能造成的內存泄漏問題分析

    Golang timer可能造成的內存泄漏問題分析

    本文探討了Golang中timer可能造成的內存泄漏問題,通過分析一段代碼,解釋了為什么協(xié)程在調用timer.Stop()后無法正常退出,文章指出,timer.Stop()并不關閉Channel,導致協(xié)程無法繼續(xù)執(zhí)行,最后,提出了一種修復方法,并呼吁大家關注和分享
    2024-12-12
  • Go利用GJSON組件解鎖JSON讀取新姿勢

    Go利用GJSON組件解鎖JSON讀取新姿勢

    Go 標準庫提供了 encoding/json 包用于處理 json 數(shù)據(jù),同時第三方庫 GJSON & SJSON 也在 json 處理方面表現(xiàn)出色,下面我們就來看看如何使用GJSON解鎖JSON讀取新方法吧
    2025-03-03
  • Go并發(fā)同步核心庫syn包的使用深度指南

    Go并發(fā)同步核心庫syn包的使用深度指南

    在?Go?語言中,并發(fā)是最重要的特性之一,sync?是?Go?標準庫中用于?并發(fā)控制與同步?的核心工具,下面小編就和大家詳細介紹一下它的具體使用吧
    2026-03-03

最新評論

金溪县| 孟村| 新密市| 武城县| 永昌县| 安宁市| 莒南县| 巧家县| 保亭| 东至县| 礼泉县| 明光市| 宁武县| 商南县| 威宁| 瓮安县| 黄陵县| 西华县| 南涧| 安龙县| 乐平市| 乌鲁木齐市| 沧州市| 泰来县| 高邮市| 阿合奇县| 濮阳市| 中西区| 黑水县| 马龙县| 遵义县| 远安县| 太白县| 遵化市| 托克托县| 冕宁县| 天镇县| 四平市| 西安市| 北川| 行唐县|