ホームページ  >  記事  >  バックエンド開発  >  Golang 同時プログラミングにおけるゴルーチンの同期と相互排他メカニズムの詳細な説明

Golang 同時プログラミングにおけるゴルーチンの同期と相互排他メカニズムの詳細な説明

PHPz
PHPzオリジナル
2023-07-20 11:25:10915ブラウズ

Golang 同時プログラミングにおけるゴルーチンの同期と相互排他メカニズムの詳細な説明

マルチコア プロセッサの普及とコンピュータのパフォーマンスの継続的な向上に伴い、複数のプロセッサ コアを最大限に活用する方法並列コンピューティングは開発者にとって重要な問題に直面しており、懸念事項となっています。同時プログラミングは、この問題を解決するための重要なテクノロジーの 1 つです。 Golang では、同時プログラミングを実装するためにゴルーチンとチャネルが広く使用されています。その中でもゴルーチンは、高い同時実行性のタスク処理を実現できる軽量なスレッドです。複数のゴルーチン間の正しい連携を確保するには、同期および相互排他メカニズムが重要な役割を果たします。

1. ゴルーチンの基本概念
Golang では、ゴルーチンは他のゴルーチンと同時に実行できる軽量のスレッドです。 Goroutine は、従来のスレッドよりも作成および破棄にかかるリソースのコストが少なく、システム リソースをより効率的に利用できます。

Goroutine はキーワード「go」を使用して作成されます。サンプル コードは次のとおりです。

package main

import (
    "fmt"
    "time"
)

func task1() {
    for i := 0; i < 5; i++ {
        fmt.Println("Task 1:", i)
        time.Sleep(time.Millisecond * 500)
    }
}

func task2() {
    for i := 0; i < 5; i++ {
        fmt.Println("Task 2:", i)
        time.Sleep(time.Millisecond * 500)
    }
}

func main() {
    go task1()
    go task2()

    time.Sleep(time.Millisecond * 3000)
}

上記のコードでは、キーワード「go」によって 2 つのゴルーチンが作成され、task1()task2()## が実行されます。 # それぞれの関数。 main() 関数では、time.Sleep() 関数を通じて 3 秒間待機し、ゴルーチンが実行を完了するのに十分な時間を確保します。

2. Goroutine の同期と相互排他メカニズム

実際の同時プログラミングでは、複数の Goroutine が特定のリソースを共有する必要がある場合があります。現時点では、リソースへの正しいアクセスを保証するために、同期および相互排他メカニズムが必要です。

    同期
  1. Golang では、一般的に使用される同期メカニズムには、WaitGroup、Mutex、および RWMutex が含まれます。
1.1 WaitGroup

WaitGroup は、Goroutine のグループの実行が完了するのを待つために使用されます。その機能は Java の CountDownLatch に似ています。サンプル コードは次のとおりです。

package main

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

func task(i int, wg *sync.WaitGroup) {
    defer wg.Done()

    fmt.Println("Task", i)
    time.Sleep(time.Millisecond * 500)
}

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go task(i, &wg)
    }

    wg.Wait()
    fmt.Println("All tasks finished")
}

上記のコードでは、待機グループ

wgsync.WaitGroup を通じて作成されます。各ゴルーチンが実行される前に wg.Add(1) を呼び出して、待機グループ カウンターを 1 ずつインクリメントし、待機する必要があるタスクがあることを示します。各ゴルーチンが実行された後、wg.Done() を呼び出して待機グループ カウンターを 1 減算し、タスクが完了したことを示します。最後に、wg.Wait() を通じてすべてのタスクが完了するまで待ちます。

1.2 Mutex

Mutex はミューテックス ロックで、同時に 1 つの Goroutine のみがアクセスできる共有リソースを保護するために使用されます。サンプル コードは次のとおりです。

package main

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

var count int
var mutex sync.Mutex

func task(i int, wg *sync.WaitGroup) {
    defer wg.Done()

    mutex.Lock()
    defer mutex.Unlock()

    count++
    fmt.Println("Task", i, "count:", count)
    time.Sleep(time.Millisecond * 500)

    mutex.Lock()
    defer mutex.Unlock()

    count--
}

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go task(i, &wg)
    }

    wg.Wait()
    fmt.Println("All tasks finished")
}

上記のコードでは、ミューテックス ロック

mutexsync.Mutex を通じて作成されます。各ゴルーチンでは、共有リソースへのアクセスは、mutex.Lock()mutex.Unlock() のペアを呼び出すことによって保護されます。実際のアプリケーションでは、保護する必要がある共有リソースを構造体に格納し、構造体のミューテックス ロックを通じて共有リソースへのアクセスを制御できます。

    相互排他
  1. 同期に加えて、特定のコード部分が同時に 1 つの Goroutine によってのみ実行されるようにするために相互排他も必要になる場合があります。 Golang で一般的に使用される相互排他メカニズムには、Once と Mutex があります。
2.1 Once

Once は、プログラムの実行中に特定のコード部分が 1 回だけ実行されるようにするために使用されます。サンプル コードは次のとおりです。

package main

import (
    "fmt"
    "sync"
)

var once sync.Once

func task() {
    fmt.Println("Task executed")
}

func main() {
    for i := 0; i < 5; i++ {
        once.Do(task)
    }
}

上記のコードでは、

sync.Once を通じて Once オブジェクト once が作成されます。各ゴルーチンで once.Do(task) を呼び出すと、プログラム実行時間全体で task() 関数が 1 回だけ実行されるようになります。

2.2 Mutex

Mutex は、相互排他を実装するために使用することもできます。サンプル コードは次のとおりです。

package main

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

var count int
var mutex sync.Mutex

func task(i int, wg *sync.WaitGroup) {
    defer wg.Done()

    mutex.Lock()
    defer mutex.Unlock()

    fmt.Println("Task", i)
    time.Sleep(time.Millisecond * 500)
}

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go task(i, &wg)
    }

    wg.Wait()
    fmt.Println("All tasks finished")
}

上記のコードでは、

mutex.Lock()mutex.Unlock() を呼び出して、 Goroutine は task() 関数を実行し、共有リソースにアクセスします。

概要

この記事の導入部を通じて、Golang 同時プログラミングにおけるゴルーチンの同期と相互排他メカニズムについて学びました。実際のアプリケーションでは、同期および相互排他メカニズムが、複数のゴルーチン間の正しい連携を確保するための鍵となります。 WaitGroup、Mutex、RWMutex などの同期および相互排他メカニズムを適切に使用すると、共有リソースへの正しいアクセスが確保され、効率的な同時プログラミングが実現します。

以上がGolang 同時プログラミングにおけるゴルーチンの同期と相互排他メカニズムの詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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