io.Readerはスレッドセーフなのか
Golang のインターフェイスにある io.Reader
は、スレッドセーフなのか。気になったので、調べてみた。
結論から言えば
os.File
は、スレッドセーフになってる- それ以外は、実装によるけど、スレッドセーフじゃないと思った方がいい
っという感じになってた。
os.File
今回は Windows 版の実装を見てみる。
https://github.com/golang/go/blob/release-branch.go1.11/src/internal/poll/fd_windows.go#L465
os.File.Read()
は、内部で poll.FD.read()
を呼び出している。
さて、この poll.FD
の実装を見てみると、独自の fdMutex
でロックをかけている。
ということで、マルチスレッドで使っても大丈夫っぽい。
func (fd *FD) Read(buf []byte) (int, error) { if err := fd.readLock(); err != nil { return 0, err } defer fd.readUnlock() // 以下、読み込み処理 }
bytes.Reader
io.Reader
の実装例として bytes.Reader
を見てみる。
https://github.com/golang/go/blob/release-branch.go1.11/src/bytes/reader.go#L39
見る限り、Mutexとかでロックをかけていない。
ということで、マルチスレッドだとちゃんと読み込めない場合がある。
func (r *Reader) Read(b []byte) (n int, err error) { if r.i >= int64(len(r.s)) { return 0, io.EOF } r.prevRune = -1 n = copy(b, r.s[r.i:]) r.i += int64(n) return }
結論
io.Reader
を複数スレッドで使うということ自体が無いとは思われるけど。
複数スレッドで使う場合は、独自にロック処理をかけること忘れないようにしよう。