goroutine的三種併發行爲控制

1. WaitGroup

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	// 適用於同一個大任務拆分爲多個小任務共同執行,最後等待所有任務同時完成結束
	var wg sync.WaitGroup
	// 需要執行兩個任務
	wg.Add(2)

	go func() {
		defer wg.Done()
		fmt.Println("this is goroutine1")
		time.Sleep(1 * time.Second)
	}()

	go func() {
		defer wg.Done()
		fmt.Println("this is goroutine2")
		time.Sleep(3 * time.Second)
	}()
    // 等待所有任務執行完畢
	wg.Wait()
	fmt.Println("all goroutine are done")
}

2. Channel

package main

import (
	"fmt"
	"time"
)

func main() {
	// 定義一個channel,等待一個任務執行,待達到某個條件時,向channel發送通知信號,通過channel+select,優雅的通知goroutine結束
	// 侷限性,不適用於控制多個goroutine,或者一個goroutine中又運行了多個goroutine
	sig := make(chan bool)

	go func() {
		for {
			select {
			case <- sig:
				fmt.Println("任務退出")
				return
			default:
				fmt.Println("任務正在執行中....")
				time.Sleep(2 * time.Second)
			}
		}
	}()

	time.Sleep(5 * time.Second)
	fmt.Println("通知任務結束執行")
	sig <- true

	// 防止main goroutine提前退出
	time.Sleep(5 * time.Second)
}

3. Context

通過控制Context上下文能夠達到多層級的goroutine同一控制的效果

package main

import (
	"context"
	"fmt"
	"time"
)

func A(ctx context.Context, name string) {
	go B(ctx, name)
	for {
		select {
		case <- ctx.Done():
			fmt.Println(name, "A退出執行")
			return
		default:
			fmt.Println(name, "A正在執行...")
			time.Sleep(2 * time.Second)
		}
	}
}

func B(ctx context.Context, name string) {
	for {
		select {
		case <- ctx.Done():
			fmt.Println(name, "B退出執行")
			return
		default:
			fmt.Println(name, "B正在執行...")
			time.Sleep(2 * time.Second)
		}
	}
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	// 模擬一個client請求
	go A(ctx, "[我乃請求1]")

	time.Sleep(3 * time.Second)
	fmt.Println("client斷開連接,通知對應請求的A,B退出")
	cancel() // 假設滿足某條件client斷開連接,那麼就向ctx中發送取消信號
	time.Sleep(3 * time.Second)
}

模擬一個client連接請求,開啓一個goroutine A,同時開啓一個goroutine B進行處理,兩個goroutine都使用context進行跟蹤,當使用cancle()函數進行退出時,兩個goroutine都會被結束.
使用context的控制能力,像一個控制器一樣,當發送退出信號時,所有基於這個context或者子context都會收到通知進行退出操作,最終釋放goroutine,解決goroutine啓動後不可控的問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章