Golang兩個協程交替輸出


題目:

現在有兩個goroutine。

一個輸出1、3、5、7、9……

另一個輸出2、4、6、8、10……

寫一段代碼,讓他們輸出1、2、3、4、5、6、7、8、9、10……

解法:

使用Go的channel來解決比較合適。

需要3個channel。

A通道用來記錄A協程的狀態。

B通道用來記錄B協程的狀態。

Exit通道用來阻塞主協程,使程序不要立即退出,而是等待我們發出退出信號以后才退出。

Go的channel具有阻塞特性,無緩沖通道中只能存放一個數據。

通道最初是空的,如果想從空通道中讀取一個數據,程序就會阻塞,直到向通道中寫入一個數據。

如果通道中有一個數據,卻沒有人來讀,程序也將阻塞,直到有人將這個數據讀走。

利用這個特性,我們在主goroutine中讀取Exit通道,因為我們還沒有向Exit通道中寫數據,主goroutine將在此阻塞。

主goroutine雖然阻塞了,其他goroutine卻是可以正常運行的。

我們設計,其他goroutine把自己的工作都做完之后,向Exit通道寫入一個數據。

主goroutine得到這個數據之后,程序不再阻塞,就可以正常退出了。

這樣我們就實現了最基本的,有多個goroutine時,工作沒做完時等待,都做完后退出的功能了。

然后我們來設計AB兩個通道。

利用無緩沖通道阻塞的特性,我們設計:

A協程輸出一個數后,向B通道寫入一個數據。

B協程輸出一個數后,也向A通道寫入一個數據。

AB都會時刻檢測自己的通道中有沒有數據,但是就像接力棒一樣,只有另一個協程可以向當前協程的通道傳遞數據。

而且傳遞完之后必須等待。

這就保證了,A干活的時候,B必須等着,不能跟A搶活干。

A干完之后,權利交給B,B干完之后,權利再交給A,直到倆人都把活干完。

這就是AB協程交替輸出的中間過程,我們還需要設計開始和結束。

開始時,我們在主goroutine中,手動向A協程發送一個開始的信號。

結束時,最后一個把活干完的人(B),向Exit通道中發送一個數據,使主goroutine退出。

實現代碼:

package main

import (
  "fmt"
)

func main() {
  // 創建3個channel,A,B和Exit
  A := make(chan bool)
  B := make(chan bool)
  Exit := make(chan bool)

  go func() {
    // 如果A通道是true,我就執行
    for i := 1; i <= 10; i += 2 {
      if ok := <-A; ok {
        fmt.Println("A 輸出", i)
        B <- true
      }
    }
  }()

  go func() {
    defer func() { Exit <- true }() // 這個協程的活干完之后,向主goroutine發送信號
    // 如果B通道是true,我就執行
    for i := 2; i <= 10; i += 2 {
      if ok := <-B; ok {
        fmt.Println("B 輸出", i)
        if i != 10 { // r如果i等於10了,就不要再向A通道寫數據了,否則將導致A通道死鎖,至於為什么,坦白說我很疑惑
          A <- true
        }
      }
    }
  }()

  A <- true // 啟動條件
  <-Exit    // 結束條件
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM