ホームページ  >  記事  >  バックエンド開発  >  golangの同期方法とは何ですか?

golangの同期方法とは何ですか?

PHPz
PHPzオリジナル
2023-03-31 10:26:11792ブラウズ

コンピューター技術の継続的な更新と発展に伴い、プログラミング言語も常に更新され、進化しています。プログラミング言語の重要な機能は、複数のスレッドの同時実行をサポートすることです。複数のスレッドを同時に実行すると、異なるスレッドが互いに干渉したり、同じリソースに同時にアクセスしたりすることが容易に発生するため、この問題を解決するには同期メソッドを使用する必要があります。

Golang は、マルチスレッドの同時実行をサポートするプログラミング言語です。多くの Golang プログラマーは、同時アクセスの問題を解決するために同期メソッドを使用します。この記事は、読者が Golang の同期メソッドの使用方法を理解できるように導きます。

同期メソッドの概要

Golang では、同期メソッドを使用することで、異なるコルーチン間のデータ同期と、複数のコルーチン間のデータ アクセスのセキュリティを確保できます。同期メソッドを使用すると、プログラマは複数のコルーチンが同時に実行されるときのデータ アクセスの競合を回避できます。 Golang では、ミューテックス ロック、rwmutex ロック、チャネルなど、同期メソッドを実装するさまざまな方法があります。

ミューテックス ロック

ミューテックス ロックは、Golang の最も基本的な同期方法であり、最も基本的なデータ同期方法を提供します。ミューテックス ロックの使用は非常に簡単で、コルーチンの同期の目的を達成するには、コルーチンの前にミューテックス ロックを追加するだけです。以下は、ミューテックス ロックを使用するサンプル コードです。

package main

import (
    "fmt"
    "sync"
)

var (
    count int
    lock sync.Mutex
)

func increment() {
    lock.Lock()
    count++
    lock.Unlock()
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            increment()
        }()
    }
    wg.Wait()
    fmt.Println(count)
}

上記のコードでは、sync.Mutex を使用してコルーチンの同期を実現します。インクリメント関数では、lock.Lock と lock.Unlock を使用してカウントをロックし、複数のコルーチンがアクセスしたときに 1 つのコルーチンのみがアクセスできるようにし、同時アクセスによるデータの競合を回避します。 main 関数では、1000 個のコルーチンを開いてインクリメント関数を呼び出し、最後に count の値を出力します。

rwmutex lock

ミューテックス ロックは同時アクセスの競合の問題を解決できますが、シナリオによっては、読み取り操作と書き込み操作の両方をサポートする必要があります。現時点では、rwmutex ロックを使用する必要があります。 Golang の rwmutex ロックは読み取り/書き込みロックであり、ロックを読み取りロックと書き込みロックの 2 つのタイプに分割します。読み取りロックは複数のコルーチンで同時に保持できますが、書き込みロックが保持されている場合は読み取りロックを取得できません。つまり、書き込みロックの方が読み取りロックよりも優先されます。

以下は、rwmutex ロックを使用するサンプル コードです:

package main

import (
    "fmt"
    "sync"
)

var (
    count int
    lock sync.RWMutex
)

func read() {
    lock.RLock()
    defer lock.RUnlock()
    fmt.Println(count)
}

func write() {
    lock.Lock()
    defer lock.Unlock()
    count++
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            read()
        }()
    }

    wg.Add(1)
    go func() {
        defer wg.Done()
        write()
    }()
    wg.Wait()
}

上記のコードでは、count 変数と sync.RWMutex を定義し、読み取り関数と書き込み関数を使用して読み取りと書き込みを行います。カウント変数。読み取り関数が呼び出されるとき、lock.RLock を使用して読み取りロックを取得し、複数のコルーチンが同時に count 変数の値を読み取ることができるようにします。 write 関数が呼び出されるとき、lock.Lock を使用して書き込みロックを取得し、1 つのコルーチンだけが count 変数の値を書き込めるようにします。 main 関数では、read 関数を呼び出すために 10 個のコルーチンを開き、write 関数を呼び出すために 1 つのコルーチンを開きます。

channel

mutex ロックと rwmutex ロックに加えて、Golang にはチャネルという別の同期方法があります。チャネルを使用すると、コルーチン間でデータを転送したり、コルーチンの実行順序を同期したりできます。チャネルには、バッファなしチャネル、バッファ付きチャネル、指向性チャネルの 3 種類があります。

以下は、非キャッシュ チャネルを使用するサンプル コードです:

package main

import (
    "fmt"
)

func main() {
    c := make(chan int, 1)
    go func() {
        c <- 1
    }()
    fmt.Println(<-c)
}

上記のコードでは、make 関数を使用して非キャッシュ チャネルを作成し、それに渡すコルーチンを定義します。そしてチャンネルデータから。 main 関数では、「<-c」ステートメントを通じてチャネル内のデータを読み取ります。

非キャッシュ チャネルの特徴は、送信と受信が同期していることです。つまり、送信操作と受信操作の前に 2 つのコルーチンを同時に準備する必要があります。そうしないと、デッドロックが発生します。

キャッシュされたチャネルとキャッシュされていないチャネルには違いがあります。キャッシュされたチャネルは、複数の要素を同時に保存できます。バッファ サイズは、チャネルの作成時に初期化されるサイズです。バッファ付きチャネルを使用する場合、送信操作はバッファがいっぱいの場合にのみブロックされ、受信操作はバッファが空の場合にのみブロックされます。

指向性チャネルは、チャネルの読み取りおよび書き込み方向を制御するために使用できます。たとえば、データの書き込みのみに使用したり、データの読み取りのみに使用したりできます。

結論

Golang の同期方法には、mutex ロック、rwmutex ロック、チャネルの 3 種類があります。これらの同期方法を使用すると、複数のコルーチンが同時に実行されるときにデータ アクセスの競合が発生しないようにできます。実際の開発では、プログラマは最適なパフォーマンスと信頼性を達成するために、実際のシナリオに基づいてさまざまな同期方法を選択する必要があります。

以上がgolangの同期方法とは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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