想用sync.RWMutex模拟一下并发读写场景下的用途,写了下面代码:
var (
useLock \= true
count \= 0
rwmutex \= sync.RWMutex{}
)
func main6() {
fmt.Println("本次执行是否使用 rwmutex? " \+ gconv.String(useLock))
waitGroup := sync.WaitGroup{}
waitGroup.Add(4)
go put(grand.Intn(100), &waitGroup)
go put(grand.Intn(100), &waitGroup)
go put(grand.Intn(100), &waitGroup)
go get(grand.Intn(50), &waitGroup)
waitGroup.Wait()
fmt.Println("并发写结束")
//最后读取等待并发组结束
readValue := make(chan int)
waitGroup.Add(1)
go read(readValue, &waitGroup)
v := <-readValue
fmt.Println("读取到count=" \+ gconv.String(v))
}
func get(num int, wait \*sync.WaitGroup) {
if useLock {
rwmutex.Lock()
defer rwmutex.Unlock()
}
defer wait.Done()
if count < num {
fmt.Println("get: can not get num:" \+ gconv.String(num) + " > count=" \+ gconv.String(count))
} else {
fmt.Println("get: can get num:" \+ gconv.String(num) + " < count=" \+ gconv.String(count))
count \= count \- num
}
fmt.Println("get: after get count=" \+ gconv.String(count))
}
func put(num int, wait \*sync.WaitGroup) {
if useLock {
rwmutex.Lock()
defer rwmutex.Unlock()
}
defer wait.Done()
fmt.Println("put: put num:" \+ gconv.String(num))
count \= count \+ num
fmt.Println("put: after put count=" \+ gconv.String(count))
}
func read(readValue chan int, wait \*sync.WaitGroup) {
if useLock {
rwmutex.RLock()
defer rwmutex.RUnlock()
}
defer wait.Done()
fmt.Println("read: read count=" \+ gconv.String(count))
readValue <- count
}
问题:get put read方法不用rwmutex,打印的结果也没感受到数据错乱,如何改一下,体现出不能保证原子性?
以下是不用rwmutex打印结果:
本次执行是否使用 rwmutex? false
get: can not get num:43 > count=0
get: after get count=0
put: put num:35
put: after put count=35
put: put num:63
put: after put count=98
put: put num:28
put: after put count=126
并发写结束
read: read count=126
读取到count=126
以下是使用rwmutex打印结果:
本次执行是否使用 rwmutex? true
put: put num:47
put: after put count=47
get: can get num:17 < count=47
get: after get count=30
put: put num:66
put: after put count=96
put: put num:13
put: after put count=109
并发写结束
read: read count=109
读取到count=109