https://qiita.com/y_matsuwitter/items/36565a3a53ac52732cae

More than 5 years have passed since last update.

昨日GoCon2014がありまして、発表の機会を頂いたのですが発表後に @rui314さんから指摘のあったグローバル変数への読み込み・書き込みの競合の問題、これに関してはsync.RWMutexを使うのがいいので、使ってみました。

通常のsync.MutexはLockのみしか提供しない。これをRead, Write双方で使ってみると非常に効率が悪くなります。そこでsync.RWMutexはRLockというもう一つのLockを提供しています。 この2つの違いは、

上記を使い分けることで効率よくLockを行えるようです。

使ってみる

実際にどう動くのか見るのが分かりやすいと思います。 play.golang.org便利なので貼っときます。http://play.golang.org/p/JJH3Tm8Sl7

rwmutex.go

package main

import (
    "sync"
    "time"
)

var mu sync.RWMutex
var data map[string]string

func main() {
    data = map[string]string{"hoge": "fuga"}
    mu = sync.RWMutex{}
    go read()
    go read()
    go write()
    go read()
    time.Sleep(5 * time.Second)
}

func read() {
    println("read_start")
    mu.RLock()
    defer mu.RUnlock()
    time.Sleep(1*time.Second)
    println("read_complete", data["hoge"])
}

func write() {
    println("write_start")
    mu.Lock()
    defer mu.Unlock()
    time.Sleep(2 * time.Second)
    data["hoge"] = "piyo"
    println("write_complete")
}

$ go run rwmutex.go
read_start
read_start
write_start
read_start
read_complete fuga
read_complete fuga
write_complete
read_complete piyo

最初のread_complete fugaの部分に関しては、RLockしているので、ほぼ同時に表示されます。 その後write->最後のreadの順にロックが解除されていって実行されています。 上記コードのRLockを全てLock, RUnlockをUnlockに書き換えると挙動の違いが見て分かりやすいかと思います。http://play.golang.org/p/-w_V4l5K2e

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles

What you can do with signing up