Golangとcontext標準ライブラリの同時実行

2685 ワード

記事リンク:https://mp.weixin.qq.com/s/FJLH4o7Y1TG9I0seiNwR_w
     https://maiyang.me/post/2018-02-12-how-to-correctly-use-context.context-in-golang/
contextは、マルチgoroutineの通知伝達とメタデータをうまく解決するGo標準ライブラリです.Goのgoroutine間には親子関係がないため,サブプロセス終了後の通知メカニズムも存在しない.複数のgoroutine協調作業は、通信、同期、通知、終了の4つの側面に関連しています.
通信:chanチャネルは各goroutine間の通信の基礎である.ここでの通信は主にプログラムのデータチャネルを指すことに注意してください.同期:バッファなしchanを使用できます.sync.WaitGroupは複数のgoroutingに同期待ち機構を提供する.mutexロックと読み書きロックメカニズム.通知:通知と上記の通信の違いは、通知の役割が管理であり、ストリームデータを制御することである.一般的な解決策は,入力端に2つのchanをバインドし,select収束処理により処理することである.この案は簡単な問題を解決できるが,汎用的な解決策ではない.終了:簡単な解決策は通知と同様に、chanとselectのブロードキャストメカニズム(close chan to broadcast)によって終了を実現する個別のチャネルを追加する.
しかし,Go間のgoroutineは平等であるため,複雑な同時構造に遭遇すると脱退メカニズムの処理が不十分になる.だからGo 1.7バージョンからcontext標準ライブラリが提供され、この問題を解決します.彼は2つの機能を提供しています.終了通知とメタデータ転送です.彼らはgoroutine呼び出しツリー全体のgoroutineに渡すことができます.同時にこれもあまり複雑ではなく、初めてGopherを勉強するのに適したソースコードです.

動作メカニズム


最初にContextを作成したgoroutineはrootノードと呼ばれます.rootノードは、Contextインタフェースを実装する特定のオブジェクトを作成し、そのオブジェクトをパラメータとして新しく引き上げられたgoroutineにコンテキストとして渡します.下流goroutineは、オブジェクトをカプセル化し続け、このクラスを下に移動します.
package main

import (
"context"
"time"
)

func main() {
// withcancel func
ctxCal, canlce := context.WithCancel(context.Background())

// withtimeout func
ctxTim, _ := context.WithTimeout(ctxCal, time.Second*3)

go work(ctxTim, "work1")
//time.Sleep(10*time.Second)

// withvalue func
ctxVal := context.WithValue(ctxTim, "key", "custom value")
go workWithValue(ctxVal, "work3")
time.Sleep(1*time.Second)
canlce()
time.Sleep(2*time.Second)
}

func workWithValue(ctx context.Context, name string) {
for {
select {
case println(name, "get message to quit")
return
default:
value := ctx.Value("key").(string)
println(name, "is running with value", value)
time.Sleep(time.Second)

}
}
}

func work(ctx context.Context, name string) {
for {
select {
case println(name, "get message to quit")
return
default:
println(name, "is running")
time.Sleep(time.Second)
}
}
}

work3 is running with value custom valuework1 is runningwork1 is runningwork3 get message to quitwork1 get message to quit
ctxbがタイムアウトして終了すると、パッケージされたすべてのサブgoroutine(ctxc)が通知され、終了が通知されることがわかります.各contextの関係構造は以下の通りである.