ホームページ >バックエンド開発 >Golang >Golang言語での同時実行実装

Golang言語での同時実行実装

王林
王林オリジナル
2023-05-10 10:06:36460ブラウズ

Golang は、Google がサーバーサイド アプリケーション用に開発したプログラミング言語です。強力な同時実行パフォーマンスの特徴があるため、分散システムや大規模な同時実行性の高いアプリケーション開発でますます広く使用されています。この記事では主にGolang言語での並行性の実装について紹介します。

1. 同時実行性と並列処理

Golang の同時実行性の実装について話す前に、同時実行性と並列性という 2 つの概念を理解する必要があります。同時実行性とは、場合によっては同じプログラム内で複数のタスクを同時に実行できる能力を指します。並列処理とは、複数のタスクを同時に実行できる機能を指します。同時実行の実現には、スレッド、プロセス、およびオペレーティング システムのその他のメカニズムの助けが必要ですが、並列処理には、マルチコア CPU などのハードウェア機能の助けが必要です。簡単に言うと、Golang の同時実行性は単一のスレッドで実装され、並列性は複数のスレッドで実装されます。

2. Golang の同時実行モデル

Golang の同時実行モデルは、Goroutine と Channel という 2 つの概念に基づいています。 Goroutine は Golang が提供する軽量スレッドで、コルーチンをベースに実装されています。スレッドと比較して、ゴルーチンの作成と破棄のオーバーヘッドが非常に小さく、ゴルーチン間の切り替えのオーバーヘッドも非常に小さいため、タスクを実行するために多数のゴルーチンを開いて実行することができ、アプリケーションの同時実行パフォーマンスが向上します。

Goroutine と同じくらい重要なのはチャネルです。 Channel は、Golang によって提供されるスレッドセーフな通信メカニズムです。チャネルを通じて、Goroutine は通信して実行を調整し、データ共有と共同作業を実現すると同時に、マルチスレッドが並行しているときに発生する可能性のある競合などの問題を回避できます。

3. Goroutine の作成と呼び出し方法

Goroutine は go キーワードを使用して作成および呼び出しできます。以下は簡単な例です:

func main() {
    go func() {
        fmt.Println("This is a Goroutine!")
    }()
    fmt.Println("This is the main function!")
    time.Sleep(time.Second)
}

上の例では、 go キーワードを使用して Goroutine を作成しました。 Goroutine の関数は匿名関数を使用して実装されます。 「This is a Goroutine!」という文字列を出力する前に、プログラムはまず「This is the main function!」という文字列を出力します。 Goroutine は非同期で実行されるため、アプリケーションは Goroutine の実行を待たずに直接終了します。 time パッケージの Sleep 関数を使用して、スレッドを一定時間待機させ、Goroutine が実行できる時間を確保できます。

4. Channel の使用

Channel は、Golang が提供するスレッドセーフな通信メカニズムです。これを使用して、Goroutine 間で情報を同期し、データを共有し、複数の Goroutine 間の競合の問題を防ぐことができます。

チャンネルの使用は非常に簡単です。まずチャンネルを作成する必要があります。チャネルを作成するには、チャネル内の要素のタイプを指定する必要があります。以下はチャネルの作成例です。

ch := make(chan int)

この例では、make 関数を使用して int 型要素を持つチャネルを作成します。

データをチャネルに送信するには、以下に示すように、チャネルの send メソッドを (<-演算子を使用して) 呼び出すことができます。

ch <- 10

この例では、int を送信します。チャンネルデータ10に入力します。チャネルがいっぱいの場合、チャネルにスペースができるまで操作はブロックされます。

チャネルからデータを受信するには、以下に示すように、(<-演算子を使用して) チャネルの受信メソッドを呼び出すことができます:

n := <-ch

この例では、チャネル データ n から int 型を受け取りました。 。チャネルが空の場合も、チャネルにデータが存在するまで操作はブロックされます。

Channel には、チャネルを閉じる close メソッド、チャネル内の要素の数を取得する len 関数などの他の操作もあります。

5. Golang 同時プログラミングの例

以下では、簡単な例を使用して Golang の同時実行実装を示します。

配列内のすべての要素の平均を計算する必要があるとします。配列内の要素の数が多いため、計算には時間がかかる場合があります。 Golang の同時実行メカニズムを使用して計算を高速化できます。

まず、int 型の 100 個の要素を含む配列 a を定義します。次に、配列内の各要素の値を計算する 10 個のゴルーチンを作成し、最後にすべての要素の合計を加算し、要素の数で割って平均を取得します。

func main() {
    a := make([]int, 100)
    for i := 0; i < len(a); i++ {
        a[i] = i
    }

    count := 10
    resultChan := make(chan int, count)
    chunkSize := len(a) / count

    for i := 0; i < count; i++ {
        startIndex := i * chunkSize
        endIndex := (i + 1) * chunkSize
        if i == count-1 {
            endIndex = len(a)
        }
        go sumChunk(a[startIndex:endIndex], resultChan)
    }

    total := 0
    for i := 0; i < count; i++ {
        total += <-resultChan
    }

    fmt.Println("Average value of array is: ", float32(total)/float32(len(a)))
}

func sumChunk(chunk []int, resultChan chan int) {
    sum := 0
    for _, v := range chunk {
        sum += v
    }
    resultChan <- sum
}

この例では、長さ 100 の int 型配列 a を定義します。長さ len(a) の配列 a に対して、count (ここでは 10) 個のゴルーチンを作成して、配列 a 内のすべての要素の合計を計算します。各ゴルーチンは配列 a の部分列の合計を計算し、その結果を resultChan に送信します。最後に、resultChan から各ゴルーチンの結果を受け取り、それらを加算してすべての要素の合計を取得し、すべての要素の平均を計算します。

実際には、通常、計算のニーズに応じてゴルーチンの数を設定します。 CPU の複数のコアを利用できる場合は、Goroutine の数を CPU コアの数に設定できます。それ以外の場合は、CPU リソースを合理的に使用するために、必要に応じてゴルーチンの数を設定する必要があります。 Goroutine が多すぎると、システムでコンテキストの切り替えなどの問題が発生し、パフォーマンスが低下する可能性があります。

以上がGolang言語での同時実行実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。