Go基礎系列:指定goroutine的執行順序


Go channel系列

當關閉一個channel時,會使得這個channel變得可讀。通過這個特性,可以實現一個goroutine執行順序的技巧。

如果一個goroutine A依賴於另一個goroutine B,在goroutine A中首先通過讀goroutine B來阻塞自己,直到goroutine B關閉自身之后,goroutine A才會繼續運行。這樣,goroutine B就先於goroutine A運行。

下面是一個指定goroutine執行順序的示例,它保證的順序是A()-->B()-->C()

package main

import (
	"fmt"
	"time"
)

// A首先被a阻塞,A()結束后關閉b,使b可讀
func A(a, b chan struct{}) {
	<-a
	fmt.Println("A()!")
	time.Sleep(time.Second)
	close(b)
}

// B首先被a阻塞,B()結束后關閉b,使b可讀
func B(a, b chan struct{}) {
	<-a
	fmt.Println("B()!")
	close(b)
}

// C首先被a阻塞
func C(a chan struct{}) {
	<-a
	fmt.Println("C()!")
}

func main() {
	x := make(chan struct{})
	y := make(chan struct{})
	z := make(chan struct{})

	go C(z)
	go A(x, y)
	go C(z)
	go B(y, z)
	go C(z)
	
	// 關閉x,讓x可讀
	close(x)
	time.Sleep(3 * time.Second)
}

上面的示例中:A goroutine被x阻塞,B goroutine被y阻塞,C goroutine被z阻塞。C依賴的z由B關閉,B依賴的y由A關閉。

如此一來,當main goroutine中的x被關閉后,A()從阻塞中釋放,繼續執行,關閉y,然后B從阻塞中釋放,繼續執行,關閉z,C得以釋放。由於z被關閉后,z仍然可讀,所以多次執行C(z)不會出問題。

A()和B()不能多次執行,因為close()不能操作已被關閉的channel。

注意,上面的channel都是struct{}類型的,整個過程中,x、y、z這3個通道都沒有傳遞數據,而是直接關閉來釋放通道,讓某些阻塞的goroutine繼續執行下去。顯然,這里的x、y、z的作用都是"信號通道",用來傳遞消息。


免責聲明!

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



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