三十路プログラマーぶろぐ

プログラマー、英語初級、三十路

【Golang】他のスレッドが読み取りしている最中にRWMutex.Lock()をかけても待機しない

表題のとおりだが、goroutineでマルチスレッド処理する場合、スレッドセーフではない値に読み書きする場合はRWMutex等を使って排他制御 (ロック) する必要がある。この際、Aスレッドが読み取り専用でBスレッドが書き込み専用だとすると、Aスレッドではロックが必要なのか確認したかった。結論から言うと必要。

これはつまり、他のスレッドが排他制御をかけずに読取している最中に、他のスレッドが読書排他制御を掛けた場合、読み取りの終わりを待ってから排他制御をかけるのか、あるいは即座に排他制御をかけて書き込み始めるのかに帰結する。これは後者、つまり読み取りの終わりを待たないことがわかった

パニックする

package main

import (
  "time"
  "sync"
  "fmt"
)

type st struct {
  sync.RWMutex
  m map[string]string
}

func main() {
  s := st{m:map[string]string{}}
  go func() {
    for {
      time.Sleep(1)
      s.Lock()
      s.m["a"] = "string"
      s.Unlock()
    }
  }()
  for {
    time.Sleep(1)
    fmt.Println(s.m["a"])
  }
}

パニックしない

package main

import (
  "time"
  "sync"
  "fmt"
)

type st struct {
  sync.RWMutex
  m map[string]string
}

func main() {
  s := st{m:map[string]string{}}
  go func() {
    for {
      time.Sleep(1)
      s.Lock()
      s.m["a"] = "string"
      s.Unlock()
    }
  }()
  for {
    time.Sleep(1)
    s.RLock()
    fmt.Println(s.m["a"])
    s.RUnlock()
  }
}