DAY 3
1
Software Development

### Hey! Go Design Patterns系列 第 3 篇

read, write 中在取得 lock 的時候，只要碰到以下兩種「衝突 conflict」狀態，就會等待此衝突結束，再取得 lock：

• read 與 write 的 lock 同時存在
• write 與 write 的 lock 同時存在

## 問題情境

``````package main

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

type Like struct {
count uint8
}

func (l *Like) Add(writerID string) {
fmt.Printf("%s change count: %d\n", writerID, l.count+1)
l.count++
}

func (l *Like) Show(readerID string) {
}

func AddLikes(writerID string, like *Like) {
for i := 0; i < 100; i++ {
}
}

for i := 0; i < 200; i++ {
}
}

func main() {
like := new(Like)
time.Sleep(10 * time.Second) //等待goroutine執行完畢
}
``````

## 解決方式

``````package main

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

type Like struct {
sync.Mutex
count uint16
}

func (l *Like) Add(writerID string) {
l.Lock()
defer l.Unlock()
fmt.Printf("%s change count: %d\n", writerID, l.count+1)
l.count++
}

func (l *Like) Show(readerID string) {
l.Lock()
defer l.Unlock()
}

func AddLikes(writerID string, like *Like) {
for i := 0; i < 100; i++ {
}
}

for i := 0; i < 200; i++ {
}
}

func main() {
like := new(Like)
time.Sleep(10 * time.Second) //等待goroutine執行完畢
}
``````

`sync.Mutex{}`換成`sync.RWMutex{}`讀寫鎖，`Show()`部分的 lock 換成 read-lock，如下：

``````package main

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

type Like struct {
sync.RWMutex
count uint16
}

func (l *Like) Add(writerID string) {
l.Lock()
defer l.Unlock()
fmt.Printf("%s change count: %d\n", writerID, l.count+1)
l.count++
}

func (l *Like) Show(readerID string) {
l.RLock()
defer l.RUnlock()
}

func AddLikes(writerID string, like *Like) {
for i := 0; i < 100; i++ {
}
}

for i := 0; i < 200; i++ {
}
}

func main() {
like := new(Like)
time.Sleep(10 * time.Second) //等待goroutine執行完畢
}
``````

B、C 多讀，A、D 單寫，使得寫入與讀取的機會都變得更有效率，如圖：

### 1 則留言

3
harveychan
iT邦新手 5 級 ‧ 2021-09-17 20:57:54