インターネット時代の到来により、プログラムの同時実行に対する人々の要求は日に日に高まっています。同時実行性の高いプログラムを開発するプロセスでは、適切な同時実行モデルを選択することが特に重要です。この記事では、Go 言語で一般的に使用されるいくつかの同時実行モデルと、それらの長所、短所、および適用可能なシナリオを紹介します。
Goroutine と Channel は、Go 言語で最も基本的で一般的に使用される同時実行モデルです。ゴルーチンは、同時実行中に CPU リソースを効率的に利用できる軽量のスレッドです。 Channel はゴルーチン間の通信方法であり、Channel を介してデータを簡単に転送して同時実行制御と同期を実現できます。
Go 言語では、キーワード go を使用して Goroutine を開始できます:
go func() { // Goroutine 执行的代码 }()
Channel を使用すると、異なる Goroutine 間の通信と同期を実現できます:
ch := make(chan int) go func() { ch <- 1 // 向通道发送数据 }() x := <-ch // 从通道接收数据
利点:
欠点:
該当するシナリオ:
WaitGroup と Mutex は、Go 言語でよく使用されるもう 1 つの同時実行モデルです。 WaitGroup を使用すると、Goroutine のグループが実行を完了するのを待機できます。一方、Mutex は、共有リソースが同時にアクセスされるのを防ぐロック メカニズムを実装するために使用されます。
WaitGroup を使用する場合、Add() メソッドを通じてカウンターの値を増やし、Done() メソッドを通じてカウンターの値を減らし、Wait() メソッドを通じてカウンターが 0 になるのを待つことができます。 ) メソッド:
var wg sync.WaitGroup for i := 0; i < num; i++ { wg.Add(1) // 增加计数器的值 go func() { // Goroutine 执行的代码 wg.Done() // 减少计数器的值 }() } wg.Wait() // 等待计数器变为 0
Mutex を使用すると、Lock() メソッドと Unlock() メソッドを通じて共有リソースへの相互排他的アクセスを実現できます:
var mu sync.Mutex mu.Lock() // 访问共享资源的代码 mu.Unlock()
利点:
欠点:
該当するシナリオ:
スレッド プールは、プログラムの開始時、タスクを同時に実行する必要がある場合に、スレッドのグループを作成できる一般的な同時実行モデルです。実行のためにスレッド プールからスレッドを取得します。スレッド プールにより、スレッドの頻繁な作成と破棄が回避され、リソースのオーバーヘッドが節約されます。
Go 言語では、標準ライブラリの goroutine プールとサードパーティ ライブラリの go-workerpool ライブラリを使用してスレッド プールを実装できます。このうち、ゴルーチン プールはローカル変数を使用したシンプルな実装です。
workerPool := make(chan chan Task, MaxWorkers) for i := 0; i < MaxWorkers; i++ { worker := NewWorker(workerPool) worker.Start() } go func() { for { select { case task := <-taskQueue: go func(task Task) { // 执行任务的代码 }(task) } } }()
利点:
欠点:
該当するシナリオ:
アクター モデルは、並行プログラムを作成するための数学的モデルであり、主にアクター、メールボックス、情報の 3 つの部分で構成されます。アクターは同時に実行されるオブジェクトとみなすことができ、各アクターにはメッセージを受信するための 1 つ以上のメールボックスがあります。メッセージは、アクター間で情報を渡すためのメカニズムです。
Go 言語では、サードパーティ ライブラリ go-actor を使用してアクター モデルを実装できます:
type HelloActor struct {} type Hello struct { Who string C chan string } func (hello HelloActor) Receive(context actor.Context) { switch msg := context.Message().(type) { case Hello: context.Respond(HelloResponse{Message: "Hello, " + msg.Who + "!"}) } } system := actor.NewActorSystem() helloActor := system.ActorOf(actor.PropsFromProducer(func() actor.Actor { return &HelloActor{} }), "hello") respChan := make(chan string) helloActor.Tell(Hello{Who: "Alice", C: respChan}) response := <-respChan fmt.Println(response)
利点:
欠点:
該当するシナリオ:
概要
この記事では主に、Go 言語で一般的に使用されるいくつかの同時実行モデルと、その利点、欠点、および適用可能なシナリオを紹介します。同時実行モデルを選択する場合、最高のパフォーマンスとスケーラビリティを得るには、実際の状況に基づいてトレードオフを行う必要があります。同時に、デッドロックやデータ競合など、同時プログラミングで発生するいくつかの一般的な問題にも注意する必要があります。
以上がGo の同時実行モデルにはどのようなオプションがありますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。