Go言語はロックをサポートしていますか?

青灯夜游
リリース: 2022-12-06 18:32:38
オリジナル
5729 人が閲覧しました

go 言語はロックをサポートしています。 Go 言語の標準ライブラリは 2 種類のロックを提供します: 1. ミューテックス ロック (sync.Mutex)、同時操作によって引き起こされ不正確なデータが生じる競合からリソースを保護できます; 2. 読み取り/書き込みロック (sync.RWMutex)、読み取りロックが占有されている場合、書き込みはブロックされますが、読み取りはブロックされません。読み取りが多く書き込みが少ない環境では、読み取り/書き込みミューテックスを最初に使用できます。

Go言語はロックをサポートしていますか?

このチュートリアルの動作環境: Windows 7 システム、GO バージョン 1.18、Dell G3 コンピューター。

Go 言語の標準ライブラリは 2 つのロックを提供します。1 つは相互排他ロック、もう 1 つは読み取り/書き込みロックです。 Go 言語パッケージの同期パッケージは、ミューテックス ロック (sync.Mutex) と読み取り/書き込みロック (sync.RWMutex) の 2 つのロック タイプを提供します。

Mutex は最も単純なタイプのロックであり、比較的暴力的でもあるため、ゴルーチンがミューテックスを取得すると、他のゴルーチンはそのゴルーチンがミューテックスを解放するまで待つことしかできません。

RWMutex は比較的使いやすく、古典的な単一書き込み複数読み取りモデルです。読み取りロックが占有されている場合、書き込みはブロックされますが、読み取りはブロックされません。つまり、複数のゴルーチンが同時に読み取りロックを取得できます (RLock() メソッドを呼び出します); 一方、書き込みロックは (Lock メソッドを呼び出します) () メソッド) は、他の goroutine (読み取りか書き込みかに関係なく) の侵入を防ぎ、ロック全体は goroutine によって排他的に所有されているのと同等です。 RWMutex の実装から判断すると、RWMutex 型は実際には Mutex を組み合わせています:

type RWMutex struct {
    w Mutex
    writerSem uint32
    readerSem uint32
    readerCount int32
    readerWait int32
}
ログイン後にコピー

これら 2 つのロック タイプの場合、Lock() または RLock() は対応する Unlock() または RUnlock() があることを確認する必要があります。そうしないと、ロックを待っているすべてのゴルーチンが不足したり、デッドロックになったりする可能性があります。 [関連する推奨事項: Go ビデオ チュートリアル プログラミング教育 ]

ロックの一般的な使用パターンは次のとおりです:

package main
import (
    "fmt"
    "sync"
)
var (
    // 逻辑中使用的某个变量
    count int
    // 与变量对应的使用互斥锁
    countGuard sync.Mutex
)
func GetCount() int {
    // 锁定
    countGuard.Lock()
    // 在函数退出时解除锁定
    defer countGuard.Unlock()
    return count
}
func SetCount(c int) {
    countGuard.Lock()
    count = c
    countGuard.Unlock()
}
func main() {
    // 可以进行并发安全的设置
    SetCount(1)
    // 可以进行并发安全的获取
    fmt.Println(GetCount())
}
ログイン後にコピー

コードの説明

  • 行 10 は、パッケージ レベルの変数であっても、構造体のメンバー フィールドであっても、特定の論理ステップで使用される変数です。

  • 行 13、通常の状況では、共有アクセスの待ち時間を短縮するために、ミューテックス ロックの粒度をできるだけ小さく設定することをお勧めします。ここで、作成者は習慣的にミューテックス変数に次の形式で名前を付けています:

变量名+Guard
ログイン後にコピー

は、ミューテックスがこの変数を保護するために使用されることを示します。

  • 16行目はカウント値を取得するための関数のカプセル化であり、この関数により変数countに安全に同時アクセスすることができます。

  • 行 19、countGuard ミューテックスをロックしてみます。 countGuard がロックされると、別の goroutine がロックを継続しようとすると、countGuard がロック解除されるまでブロックされます。

  • 行 22 では、defer を使用して countGuard のロック解除呼び出しを遅延させています。ロック解除操作は、GetCount() 関数が返されたときに発生します。

  • 行 27 でカウント値を設定する場合、countGuard はロックおよびロック解除操作の実行にも使用され、カウント値を変更するプロセスがアトミックなプロセスであり、同時アクセスの競合が発生しないようにします。が発生します。

読み取りが多く書き込みが少ない環境では、ミューテックスよりも効率的な読み取り/書き込みミューテックス (sync.RWMutex) の使用を優先できます。 。 sync パッケージの RWMutex は、読み取り/書き込みミューテックスのカプセル化を提供します。

ミューテックスの例のコードの一部を読み取り/書き込みミューテックスに変更しました。以下のコードを参照してください:

var (
    // 逻辑中使用的某个变量
    count int
    // 与变量对应的使用互斥锁
    countGuard sync.RWMutex
)
func GetCount() int {
    // 锁定
    countGuard.RLock()
    // 在函数退出时解除锁定
    defer countGuard.RUnlock()
    return count
}
ログイン後にコピー

コードの説明は次のとおりです:

  • #6 行目では、countGuard を宣言するときに、sync.Mutex ミューテックス ロックを sync.RWMutex 読み取り/書き込みミューテックス ロックに変更します。

  • 12行目のカウント取得処理は、カウントデータを読み込む処理であり、読み書きミューテックスロックに適しています。この行では、countGuard.Lock() を countGuard.RLock() に置き換えて、読み取り/書き込みミューテックスを読み取りとしてマークします。別のゴルーチンが同時に countGuard にアクセスし、同時に countGuard.RLock() を呼び出した場合、ブロックは発生しません。

  • 行 15 は読み取りモードのロックに対応し、読み取りモードを使用してロックを解除します。

#特記事項:

    sync.Mutex のロックはネストできません
  • ##sync.RWMutex の RLock() はネストできます
  • sync.RWMutex の mu.Lock() はネストできません
  • mu.RLock() を sync.RWMutex の mu.Lock() にネストすることはできません
  • プログラミング関連の知識の詳細については、次のリンクを参照してください:
プログラミング ビデオ

! !

以上がGo言語はロックをサポートしていますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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