Skip to content

Instantly share code, notes, and snippets.

@kitak
Created October 27, 2013 04:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kitak/7177880 to your computer and use it in GitHub Desktop.
Save kitak/7177880 to your computer and use it in GitHub Desktop.
Javaデザパタ本 マルチスレッド編 section6 「read-write lockパターン」
// read-write lockパターン
// 読む処理同士が衝突しないことを利用してパフォーマンスをあげる
// コンテキスト
// - 読む処理が重く、ひとつのReaderがリソースを占有するとパフォーマンスが落ちる状況
// - 読む頻度が書く頻度よりも高い状況
package main
import "fmt"
import "sync"
import "time"
import "math/rand"
// shared resource役
type Data struct {
Size int
Buffer []string
sync.RWMutex // readwrite lock役
}
func (self *Data) Init(size int) {
self.Size = size
for i := 0; i < self.Size; i++ {
self.Buffer = append(self.Buffer, "*")
}
}
func (self *Data) Read() []string {
defer self.RUnlock()
// 読み込みのためのロック。アンロックされるまで書き込めない
self.RLock()
return self.doRead()
}
func (self *Data) Write(s string) {
defer self.Unlock()
// 読み込み・書き込みのロック。アンロックされるまで読み込めない、書き込めない
self.Lock()
self.doWrite(s)
}
func (self *Data) doRead() []string {
newbuf := make([]string, 10)
copy(newbuf, self.Buffer)
self.slowly()
return newbuf
}
func (self *Data) doWrite(s string) {
for i := 0; i < len(self.Buffer); i++ {
self.Buffer[i] = s
}
self.slowly()
}
func (self *Data) slowly() {
time.Sleep(time.Millisecond*50)
}
// writer 役
type Writer struct {
data *Data
filler string
index int
}
func (self *Writer) Start() {
for {
s := self.nextStr()
self.data.Write(s)
time.Sleep(time.Millisecond*time.Duration(rand.Intn(3000)))
}
}
func (self *Writer) nextStr() string {
s := string(self.filler[self.index])
self.index += 1
if self.index >= len(self.filler) {
self.index = 0
}
return s
}
// reader 役
type Reader struct {
data *Data
}
func (self *Reader) Start() {
for {
readbuf := self.data.Read()
fmt.Println("reads ", readbuf)
}
}
func main() {
data := &Data{}
data.Init(10)
reader1 := &Reader{data}
reader2 := &Reader{data}
reader3 := &Reader{data}
reader4 := &Reader{data}
reader5 := &Reader{data}
reader6 := &Reader{data}
writer1 := &Writer{data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0}
writer2 := &Writer{data, "abcdefghijklmnopqrstuvwxyz", 0}
go reader1.Start()
go reader2.Start()
go reader3.Start()
go reader4.Start()
go reader5.Start()
go reader6.Start()
go writer1.Start()
go writer2.Start()
for {
time.Sleep(100)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment