/*
go状态协程
在上面的例子中 我们演示了如何通过使用
mutex来在多个协程之间共享状态
另外一种方法是使用协程内置的同步机制来实现
这种基于通道的方法和go的通过消息共享内存
保证每份数据为单独的协程所有的理念一直的
*/
package main
import (
"fmt"
"math/rand"
"sync/atomic"
"time"
)
/*
在这个例子中 将有一个单独的协程拥有这个状态
这样可以保证这个数据不会被并行访问所破坏
为了读写这个状态
其他协程将向这个协程发送信息并且相应地接收返回信息
这些readOp writeOp 封装了这些请求和恢复
*/
type readOp struct {
key int
resp chan int
}
type writeOp struct {
key int
val int
resp chan bool
}
func main() {
var ops int64 = 0
/*
reads 和writes通道将被其他协程用来从中读取或写入数据
*/
reads := make(chan *readOp)
writes := make(chan *writeOp)
/*
这个是拥有state的协程 state是一个协程的私有map
这个协程不断地select通道reads writes
当有请求来临的时候进行恢复
*/
go func() {
var state = make(map[int]int)
for {
select {
case read := <-reads:
read.resp <- state[read.key]
case write := <-writes:
state[write.key] = write.val
write.resp <- true
}
}
}()
for r := 0; r < 100; r++ {
go func(){
for {
read := &readOp{
key : rand.Intn(5),
resp: make(chan int)
}
reads <- read
<-read.resp
atomic.AddInt64(&ops, 1)
}
}()
}
for w :=0; w <10; w++ {
go func(){
for {
write := &writeOp{
key:randIntn(5),
val:rand.Intn(100).
resp:make(chan bool)
}
writes<-write
<-write.resp
atomic.AddInt64(&ops, 1)
}
}()
}
time.Sleep(time.Second)
opsFinal := atomic.LoadInt64(&ops)
fmt.Println(opsFinal)
}
/*
基于协程的方法比基于mutex的方法更加复杂一
*/