ホームページ >バックエンド開発 >Golang >Go言語のロック機構を詳しく解説した記事

Go言語のロック機構を詳しく解説した記事

PHPz
PHPzオリジナル
2023-04-13 18:12:031682ブラウズ

同時実行性の高いプログラミング言語として、Go 言語の同時実行性制御メカニズムは非常に重要です。最も一般的に使用される機構の 1 つはロック機構です。この記事ではGo言語でロック機構を実装する方法を紹介します。

Go 言語のロック

Go 言語で最も一般的に使用されるロックは、ミューテックス ロック (Mutex) です。ミューテックスは、共有リソースへのアクセスを制御するために使用される特別なバイナリ セマフォです。 Go 言語は、標準ライブラリの「sync」パッケージを通じてミューテックス ロック機能を提供します。ミューテックス ロックのタイプは次のように定義されます。

type Mutex struct {
    state int32
    sema  uint32
}

状態フィールドはロックのステータスを記録するために使用され、sema フィールドはセマフォです。

ミューテックス ロックを使用する前に、Lock メソッドを呼び出してロックを取得する必要があります。ロックがすでに別のコルーチンによって保持されている場合、現在のコルーチンはブロックされ、ロックが解放されるのを待ちます。例:

var mu sync.Mutex
// ...
mu.Lock()
// ...
mu.Unlock()

このコードでは、mu はミューテックス ロックです。 mu.Lock() はロックの取得に使用されます。ロックがすでに他のコルーチンによって保持されている場合、現在のコルーチンはブロックされます。 mu.Unlock() はロックを解除するために使用されます。

このメカニズムは非常に単純ですが、実際にはあまり効率的ではありません。同じミューテックスを取得しようとするコルーチンが多数あると処理中に輻輳が発生しやすくなり、プログラム全体の効率が低下します。

読み取り/書き込みロック

読み取りおよび書き込み操作が必要な一部のシナリオでは、ミューテックス ロックの効率は非常に低くなります。ミューテックス ロックは、同時に 1 つのコルーチンのみが共有リソースにアクセスできることを保証できるため、読み取り操作と書き込み操作の両方で、最初にロックが解放されるまで待機する必要があります。ただし、読み取り操作のみの場合は、この待ち時間は必要ありません。複数のコルーチンは、データに破壊的な変更を加えることなく、同じリソースを同時に読み取ることができるためです。

現時点では、読み取り/書き込みロック (RWMutex) を使用する必要があります。読み取り/書き込みロックは、特別な種類の相互排他ロックです。リソースは複数のコルーチンによって同時に読み取ることができますが、書き込むことができるのは 1 つのコルーチンのみです。したがって、書き込み操作中はすべての読み取り操作がブロックされ、書き込み操作が完了するまで待機します。読み取り/書き込みロックのタイプは次のように定義されます。

type RWMutex struct {
    w           Mutex // 用于写操作的互斥锁
    writerSem   uint32
    readerSem   uint32
    readerCount int32  // 当前进行读操作的协程数量
    readerWait  int32  // 等待读操作的协程数量
}

読み取り/書き込みロックには、読み取りロックと書き込みロックの 2 つの状態があります。読み取りロック状態では、複数のコルーチンが同時に読み取り操作を実行できますが、書き込みロック状態では、1 つのコルーチンのみが書き込み操作を実行できます。同時に、読み取り/書き込みロックはコルーチンの優先順位メカニズムをサポートしています。つまり、待機時間が長いコルーチンが最初にロックを取得します。

読み取りロックを取得するメソッドは RLock()、読み取りロックを解放するメソッドは RUnlock()、書き込みロックを取得するメソッドはLock() 、書き込みロックを解除するメソッドは Unlock() です。例:

var rw sync.RWMutex
// ...
func read() {
    rw.RLock()
    // ...
    rw.RUnlock()
}
// ...
func write() {
    rw.Lock()
    // ...
    rw.Unlock()
}

このコードは、Go 言語で読み取り/書き込みロックを使用する方法を示しています。 read() 関数は読み取りロックを取得し、複数のコルーチンによって同時に呼び出すことができますが、write() 関数は書き込みロックを取得し、コルーチンを 1 つだけ持つことができます。同時に電話してください。

sync.Once

sync.Once は非常に便利なロックです。初期化操作は 1 回だけ実行されます。 Once の内部にはブール値があり、ロックされている場合、呼び出しが失敗すると、後続の呼び出しはすぐに戻り、初期化は再実行されません。

func singleton() {
    var once sync.Once
    once.Do(func() {
        // 初始化对象
    })
    // 使用对象
}

sync.Once を使用すると、複数のコルーチンで初期化操作を繰り返すことを回避できます。

概要

Go 言語では、マルチスレッド同時実行制御を実装するメカニズムが非常に重要です。ミューテックス ロック、読み取り/書き込みロック、ワンスなどのメカニズムを使用すると、同時操作を処理する際のプログラムの効率と安全性が向上します。実際には、特定のシナリオに応じてさまざまなメカニズムを選択する必要があり、選択して使用する前に特定のテストと検証を実行する必要があります。

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

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