[Go言語]RWMutexの考察

こんにちは。KOUKIです。

ここで紹介するコードは、以下の書籍からの引用です。

ここでは、RWMutexを紹介します。

RWMutexとは

sync.RWMutexは、Mutexと概念的には同じもので、メモリのアクセスを保護します。
※メモリのアクセス保護とは、プロセスの中で書込や読込を一つのプロセスだけが行えるようにすることをここでは指しています

しかし、Mutexよりメモリに対する管理機構を多く提供しています。

複数の並行処理のプロセスで共有するメモリがあったとしても、そのプロセスの全てが書込や読込の両方を必要としているわけではないです。

RWMutexは、「メモリに対する読み込みのロックを要求した場合、ロックが書き込みで保持されていなければ、アクセスを得ることができる」などの制御が可能です。

引用コード

考察

出力結果

先に出力結果を見ておきましょう。

このプログラムは、RWMutexとMutexの処理スピードの差を表しています。

私のPCだとそれほど効果的な結果にならないですね。

しかし、本来、メモリのロック(クリティカルセクションの切り替え)にはある程度の時間的コストがかかるので、RWMutexを使う方が効率的なロックを行えることがあるようです。

sync.Lockerについて

sync.Lockerはinterfaceで、Mutex/RWMutex型を満たしています。

Mutex、RWMutexのソースコードを追って見ると以下のようにLockerインターフェースを実装しているのがわかります。

これにより、Producer, observer, testのそれぞれのsync.LockerにMutex型、RWMutex型を渡すことができます。

producerとobserver

producerは生産者、observerは消費者です。

ここでは、producerを1ナノ秒間スリープさせてobserverより非活発にしているようです。これにより意図的に読込処理のプロセスを書込処理のプロセスより多く実行されるようにしています。

RWMutexは、以下の構造体になっています。

RWMutexは、Mutexをラップしています。

そのため、以下のようにLockを呼び出すとMutexのLockが呼ばれるっぽいです。

一方、m.RLocker()は何者でしょうか。

RLockerはインターフェースのようです。

そして、このインターフェースを介して、LockとUnlockを呼び出すと、それぞれRLock、RUnlockが呼ばれるようですね。

呼び出し先でLock,とRLock、RUnlockとRUnlockとを意識しないで使えるので、並行処理とは別にこの実装パターンは覚えておいて損はなさそうですね。

テーブル出力

出力結果で表示したテーブルですが、これはtabwriterを使って出力しています。

色々なツールに使えそうなので、便利そうです。

おわりに

並行処理は難しい!

気を抜くとすぐにバグになるし、新しい用語やらパターンやらがいっぱい出てくるしで大変です。

しかし、並行処理プログラミングが実装できるようになると様々なものに応用できるので、マスターしておきたいところです。

それでは、また!

関連記事

オススメ