GoLang RWMutex
このチュートリアルでは、GoLang で rwmutex
を使用する方法を示します。
GoLang RWMutex
mutex
は相互排除の略で、変数にアクセスしたスレッドをいつでも追跡するために使用されます。 ミューテックスは、GoLang の sync
パッケージで提供されるデータ構造です。
mutex
は、Go コードを使用して同時実行を実行するときに使用されます。 これは、GoLang で mutex
を使用する簡単な例です。
package main
import (
"fmt"
"sync"
"time"
)
func EvenNumber(num int) bool {
return num%2 == 0
}
func main() {
num := 2
var DemoMutex sync.Mutex
go func() {
DemoMutex.Lock()
defer DemoMutex.Unlock()
EvenNum := EvenNumber(num)
time.Sleep(5 * time.Millisecond)
if EvenNum {
fmt.Println("The number", num, " is even")
return
}
fmt.Println("The number", num, "is odd")
}()
go func() {
DemoMutex.Lock()
num++
DemoMutex.Unlock()
}()
time.Sleep(time.Second)
}
上記のコードは、数値が偶数か奇数かをチェックします。 ここで、同時実行の goroutine
はデータを破損する可能性があるため、mutex
を使用してデータをロックおよびロック解除し、破損を防ぎます。
出力を参照してください。
The number 2 is even
mutex
と RWmutex
は異なり、mutex
は単純なミューテックスであり、RWmutex
はリーダー/ライターの相互排他ロックです。 RWMutex
を使用すると、ロックは任意の数のリーダーまたは 1つのライターによって保持されます。
RWMutex
の値がゼロの場合、ロックされていないミューテックスです。 RWMutex
ミューテックスで同じ例を試してみましょう。
package main
import (
"fmt"
"sync"
"time"
)
func EvenNumber(num int) bool {
return num%2 == 0
}
func main() {
num := 2
var DemoRWM sync.RWMutex
// both goroutines call DemoRWM.Lock() before accessing `num` and then call the DemoRWM.Unlock after they are done
go func() {
DemoRWM.RLock()
defer DemoRWM.RUnlock()
EvenNum := EvenNumber(num)
time.Sleep(5 * time.Millisecond)
if EvenNum {
fmt.Println("The number", num, " is even")
return
}
fmt.Println("The number", num, "is odd")
}()
go func() {
DemoRWM.Lock()
num++
DemoRWM.Unlock()
}()
time.Sleep(time.Second)
}
ここでわかるように、両方の goroutines
は num
にアクセスする前に DemoRWM.Lock()
を呼び出し、完了後に DemoRWM.Unlock
を呼び出します。 コードは RWMutex
を使用しています。
出力を参照してください。
The number 2 is even
RWMutex
の別の例を試してみましょう。ここで、RWMutex
はすべてのリーダーが同時にデータにアクセスできるようにし、ライターは他のユーザーをロックアウトします。
例を参照してください。
package main
import (
"fmt"
"sync"
)
func main() {
DemoMap := map[int]int{}
DemoRWM := &sync.RWMutex{}
go LoopWrite(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
go LoopRead(DemoMap, DemoRWM)
// stop the program from exiting must be killed
StopBlock := make(chan struct{})
<-StopBlock
}
func LoopRead(DemoMap map[int]int, DemoRWM *sync.RWMutex) {
for {
DemoRWM.RLock()
for k, v := range DemoMap {
fmt.Println(k, "-", v)
}
DemoRWM.RUnlock()
}
}
func LoopWrite(DemoMap map[int]int, DemoRWM *sync.RWMutex) {
for {
for i := 0; i < 100; i++ {
DemoRWM.Lock()
DemoMap[i] = i
DemoRWM.Unlock()
}
}
}
ご覧のとおり、RWMutex
を使用すると、read
を何度でも使用できます。 このコードの出力は次のようになります。
timeout running program
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
0 - 0
1 - 1
Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.
LinkedIn Facebook