ホームページ > バックエンド開発 > Golang > Golang は同時実行性を実装します

Golang は同時実行性を実装します

WBOY
リリース: 2023-05-16 09:44:37
オリジナル
1107 人が閲覧しました

コンピュータ技術の継続的な進歩に伴い、最新のプログラムの動作効率とパフォーマンスがますます重要な問題になっています。同時プログラミングは、プログラムの実行効率とパフォーマンスを向上させる重要な方法です。新興プログラミング言語である golang の独自の goroutine およびチャネル メカニズムにより、同時プログラミングがよりシンプルかつ効率的に行われます。

この記事では、golang 同時プログラミングの基本概念を紹介し、いくつかの例を使用してゴルーチンとチャネルを使用して効率的な同時プログラムを構築する方法を示します。

1. goroutine とは

Goroutine は golang の軽量スレッドで、各 goroutine のサイズはわずか約 2KB で、占有するメモリとリソースはほとんどありません。さらに、golang のスケジューラは、同時実行を実現するために、実行用のゴルーチンを異なる物理スレッドに自動的に割り当てます。

go キーワードを使用してゴルーチンを開始できます。例:

package main

import (
    "fmt"
    "time"
)

func printNums() {
    for i := 0; i < 5; i++ {
        fmt.Println(i)
        time.Sleep(time.Millisecond * 500)
    }
}

func main() {
    // 启动一个goroutine
    go printNums()

    // 继续执行主goroutine
    for i := 0; i < 5; i++ {
        fmt.Println("Hello")
        time.Sleep(time.Millisecond * 500)
    }
}
ログイン後にコピー

上記のプログラムを実行すると、2 つのゴルーチンが交互に数値と Hello を出力し、同時実行が実現していることがわかります。

2. チャネルとは

Golang のチャネルは、ゴルーチン間の通信と同期に使用されるデータ構造です。チャネルは複数のゴルーチン間でデータを転送し、チャネルの同期メカニズムを通じて安全なデータ交換を実現できます。チャネルには、バッファ付きチャネルとバッファなしチャネルの 2 種類があります。バッファリングされていないチャネルでの送受信操作は、対応する受信操作と送信操作が発生するまでブロックされます。バッファリングされたチャネルにより、送信操作と受信操作の間の時間差をある程度軽減できます。

バッファ付きチャネルの使用例を次に示します:

package main

import (
    "fmt"
    "time"
)

func main() {
    // 创建一个大小为2的带缓冲通道
    ch := make(chan string, 2)

    // 启动两个goroutine
    go func() {
        ch <- "Hello"
        ch <- "World"
    }()
    go func() {
        time.Sleep(time.Second)
        fmt.Println(<-ch)
        fmt.Println(<-ch)
    }()

    // 等待goroutine执行完毕
    time.Sleep(time.Second * 2)
}
ログイン後にコピー

上の例では、サイズ 2 のバッファ付きチャネルを作成します。次に 2 つのゴルーチンが開始され、1 つは 2 つの文字列をチャネルに送信し、もう 1 つはチャネルから 2 つの文字列を受信して​​出力を出力します。バッファの存在により、送信操作と受信操作の間には一定の時間差が生じますが、データはチャネルを通じて転送および同期できます。

バッファリングされたチャネルに加えて、golang はバッファリングされていないチャネルもサポートしており、ゴルーチン間の同期をより厳密に保証できます。

3. ゴルーチンとチャネルを使用して同時実行を実現する方法

前の紹介を通じて、ゴルーチンとチャネルが golang の非常に便利な同時プログラミング ツールであることがわかりました。以下に、それらを使用して並行プログラミングを実装する方法の例をいくつか紹介します。

1. 複数の Web ページを同時にダウンロードする

ゴルーチンとチャネルを通じて、複数の Web ページを同時に簡単にダウンロードできます。例:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

// 下载网页的函数
func download(url string, ch chan<- string) {
    resp, err := http.Get(url)
    if err != nil {
        ch <- fmt.Sprintf("%s error: %v", url, err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        ch <- fmt.Sprintf("%s error: %v", url, err)
        return
    }
    ch <- fmt.Sprintf("%s=%d", url, len(body))
}

func main() {
    // 要下载的网页列表
    urls := []string{
        "https://www.baidu.com",
        "https://www.google.com",
        "https://www.github.com",
    }

    // 创建一个无缓冲通道
    ch := make(chan string)

    // 启动多个goroutine下载网页
    for _, url := range urls {
        go download(url, ch)
    }

    // 从通道中读取结果,并打印输出
    for range urls {
        fmt.Println(<-ch)
    }

    // 等待goroutine执行完毕
    time.Sleep(time.Second * 2)
}
ログイン後にコピー

上記の例では、指定された URL の Web ページのコンテンツをダウンロードし、チャネルを通じて結果を返すダウンロード関数を定義しました。次に、for ループを通じて複数のゴルーチンを開始し、各ゴルーチンがダウンロード関数を呼び出して Web ページをダウンロードしました。ダウンロード結果がチャネルを通じて返された後、メインのゴルーチンで読み取られて出力されます。このようにして、複数の Web ページを同時に簡単にダウンロードし、プログラムの操作効率とパフォーマンスを向上させることができます。

2. 複数のタスクを同時に処理する

Web ページをダウンロードするだけでなく、ゴルーチンとチャネルを使用して複数のタスクを同時に処理することもできます。例:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func worker(id int, jobs <-chan int, results chan<- int) {
    for i := range jobs {
        fmt.Printf("worker %d start job %d
", id, i)
        time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
        fmt.Printf("worker %d finish job %d
", id, i)
        results <- i * 2
    }
}

func main() {
    // 定义要处理的任务列表
    jobCount := 10
    jobs := make(chan int, jobCount)
    for i := 0; i < jobCount; i++ {
        jobs <- i
    }
    close(jobs)

    // 定义结果通道
    results := make(chan int, jobCount)

    // 启动多个goroutine处理任务
    workerCount := 3
    for i := 0; i < workerCount; i++ {
        go worker(i, jobs, results)
    }

    // 从结果通道中读取结果,并打印输出
    for j := 0; j < jobCount; j++ {
        fmt.Println(<-results)
    }

    // 等待goroutine执行完毕
    time.Sleep(time.Second * 2)
}
ログイン後にコピー

上の例では、指定されたタスクの処理をシミュレートするワーカー関数を定義しました。次に、for ループを通じて複数の goroutine を開始し、各 goroutine がジョブ チャネルからタスクを読み取り、処理しました。処理結果は結果チャネルを通じて返されます。最後に、すべての結果がメインのゴルーチンの結果チャネルから読み取られて出力されます。このようにして、複数のタスクを同時に簡単に処理し、プログラムの実行効率とパフォーマンスを向上させることができます。

4. 概要

この記事では、ゴルーチンとチャネルの使用を含む、golang 同時プログラミングの基本概念を紹介します。複数の例を通して、ゴルーチンとチャネルを使用して効率的な同時プログラムを構築する方法を示します。他のプログラミング言語と比較して、golang の同時プログラミング モデルはより簡潔かつ効率的であり、プログラムの実行効率とパフォーマンスが大幅に向上します。ただし、高品質の同時実行プログラムを作成するのは簡単ではなく、golang 同時実行プログラミングのメカニズムと原則を深く理解し、習得する必要があることに注意してください。

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

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート