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

Go語(yǔ)言無(wú)緩沖的通道的使用

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

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

如果兩個(gè) goroutine 沒(méi)有同時(shí)準(zhǔn)備好,通道會(huì)導(dǎo)致先執(zhí)行發(fā)送或接收操作的 goroutine 阻塞等待。這種對(duì)通道進(jìn)行發(fā)送和接收的交互行為本身就是同步的。其中任意一個(gè)操作都無(wú)法離開(kāi)另一個(gè)操作單獨(dú)存在。

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

同步指的是在兩個(gè)或多個(gè)協(xié)程(線(xiàn)程)之間,保持?jǐn)?shù)據(jù)內(nèi)容一致性的機(jī)制。

下圖展示兩個(gè) goroutine 如何利用無(wú)緩沖的通道來(lái)共享一個(gè)值。

使用無(wú)緩沖的通道在 goroutine 之間同步

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

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

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

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

【示例 1】在網(wǎng)球比賽中,兩位選手會(huì)把球在兩個(gè)人之間來(lái)回傳遞。選手總是處在以下兩種狀態(tài)之一,要么在等待接球,要么將球打向?qū)Ψ?。可以使用兩個(gè) goroutine 來(lái)模擬網(wǎng)球比賽,并使用無(wú)緩沖的通道來(lái)模擬球的來(lái)回,代碼如下所示。

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

運(yùn)行這個(gè)程序,輸出結(jié)果如下所示。

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

代碼說(shuō)明如下:

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

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

// 這個(gè)示例程序展示如何用無(wú)緩沖的通道來(lái)模擬
// 4 個(gè)goroutine 間的接力比賽
package main
import (
    "fmt"
    "sync"
    "time"
)
// wg 用來(lái)等待程序結(jié)束
var wg sync.WaitGroup
// main 是所有Go 程序的入口
func main() {
    // 創(chuàng)建一個(gè)無(wú)緩沖的通道
    baton := make(chan int)
    // 為最后一位跑步者將計(jì)數(shù)加1
    wg.Add(1)
    // 第一位跑步者持有接力棒
    go Runner(baton)
    // 開(kāi)始比賽
    baton <- 1
    // 等待比賽結(jié)束
    wg.Wait()
}
// Runner 模擬接力比賽中的一位跑步者
func Runner(baton chan int) {
    var newRunner int
    // 等待接力棒
    runner := <-baton
    // 開(kāi)始繞著跑道跑步
    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)
    // 比賽結(jié)束了嗎?
    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
}

運(yùn)行這個(gè)程序,輸出結(jié)果如下所示。

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

代碼說(shuō)明如下:

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

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

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

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

相關(guān)文章

  • Golang使用原生http實(shí)現(xiàn)中間件的代碼詳解

    Golang使用原生http實(shí)現(xiàn)中間件的代碼詳解

    中間件(middleware):常被用來(lái)做認(rèn)證校驗(yàn)、審計(jì)等,家常用的Iris、Gin等web框架,都包含了中間件邏輯,但有時(shí)我們引入該框架顯得較為繁重,本文將介紹通過(guò)golang原生http來(lái)實(shí)現(xiàn)中間件操作,需要的朋友可以參考下
    2024-05-05
  • Go素?cái)?shù)篩選分析詳解

    Go素?cái)?shù)篩選分析詳解

    學(xué)習(xí)Go語(yǔ)言的過(guò)程中,遇到素?cái)?shù)篩選的問(wèn)題。這是一個(gè)經(jīng)典的并發(fā)編程問(wèn)題,是某大佬的代碼,短短幾行代碼就實(shí)現(xiàn)了素?cái)?shù)篩選,這篇文章主要介紹了Go素?cái)?shù)篩選分析,需要的朋友可以參考下
    2022-10-10
  • Go語(yǔ)言實(shí)現(xiàn)超時(shí)的三種方法實(shí)例

    Go語(yǔ)言實(shí)現(xiàn)超時(shí)的三種方法實(shí)例

    超時(shí)在一些業(yè)務(wù)場(chǎng)景里非常普遍,下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言實(shí)現(xiàn)超時(shí)的三種方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Go語(yǔ)言具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-07-07
  • Go語(yǔ)言并發(fā)范式之future模式詳解

    Go語(yǔ)言并發(fā)范式之future模式詳解

    編程中經(jīng)常遇到在一個(gè)流程中需要調(diào)用多個(gè)子調(diào)用的情況,此時(shí)就可以使用Go并發(fā)編程中的future模式,下面小編就來(lái)和大家聊聊future模式的具體使用,需要的可以參考一下
    2023-06-06
  • go語(yǔ)言編程之select信道處理示例詳解

    go語(yǔ)言編程之select信道處理示例詳解

    這篇文章主要為大家介紹了go語(yǔ)言編程之select信道處理示例詳解,<BR>有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • golang語(yǔ)言中for循環(huán)語(yǔ)句用法實(shí)例

    golang語(yǔ)言中for循環(huán)語(yǔ)句用法實(shí)例

    這篇文章主要介紹了golang語(yǔ)言中for循環(huán)語(yǔ)句用法,實(shí)例分析了for循環(huán)遍歷的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-01-01
  • Go語(yǔ)言操作redis數(shù)據(jù)庫(kù)的方法

    Go語(yǔ)言操作redis數(shù)據(jù)庫(kù)的方法

    這篇文章主要介紹了Go語(yǔ)言操作redis數(shù)據(jù)庫(kù)的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • 淺談go中defer的一個(gè)隱藏功能

    淺談go中defer的一個(gè)隱藏功能

    這篇文章主要介紹了淺談go中defer的一個(gè)隱藏功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Go語(yǔ)言中日志的規(guī)范使用建議分享

    Go語(yǔ)言中日志的規(guī)范使用建議分享

    在任何服務(wù)端的語(yǔ)言項(xiàng)目中,日志是至關(guān)重要的組成部分,本文為大家整理了一些如何規(guī)范使用GO語(yǔ)言日志的建議,以及相應(yīng)的實(shí)際示例,希望對(duì)大家有事幫助
    2024-01-01
  • Go語(yǔ)言讀取,設(shè)置Cookie及設(shè)置cookie過(guò)期方法詳解

    Go語(yǔ)言讀取,設(shè)置Cookie及設(shè)置cookie過(guò)期方法詳解

    這篇文章主要介紹了Go語(yǔ)言讀取,設(shè)置Cookie及設(shè)置cookie過(guò)期方法詳解,需要的朋友可以參考下
    2022-04-04

最新評(píng)論