038_go语言中的状态协程
代码演示:
package main import ( "fmt" "math/rand" "sync/atomic" "time" ) type read0p struct { key int resp chan int } type write0p struct { key int val int resp chan bool } func main() { var read0ps uint64 = 0 var write0ps uint64 = 0 reads := make(chan *read0p) writes := make(chan *write0p) 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 := &read0p{ key: rand.Intn(5), resp: make(chan int)} reads <- read <-read.resp atomic.AddUint64(&read0ps, 1) time.Sleep(time.Millisecond) } }() } for w := 0; w < 10; w++ { go func() { for { write := &write0p{ key: rand.Intn(5), val: rand.Intn(100), resp: make(chan bool)} writes <- write <-write.resp atomic.AddUint64(&write0ps, 1) time.Sleep(time.Millisecond) } }() } time.Sleep(time.Second) read0psFinal := atomic.LoadUint64(&read0ps) fmt.Println("read0ps:", read0psFinal) write0psFinal := atomic.LoadUint64(&write0ps) fmt.Println("write0ps:", write0psFinal) }
代码运行结果:
read0ps: 77702 write0ps: 7770
代码解读:
- 本例子中的代码思路,和上一个例子中的代码思路大致相同,只是用协程通道来实现的
- 在本例中,我们对state这个map进行读写操作,但是为了安全性和唯一性,我们让某一个协程单独拥有state这个map
- 当某个协程想要对state进行操作的话,就发送请求到拥有state的这个协程中,然后再接收返回的结果
- 本例中,有两个重要通道,分别是读reads和写writes,拥有state这个map的协程会监听这两个通道
- 然后两个读read0ps和写write0ps的结构体中,又分别单独有一个通道用来存储结果
- 当协程A想进行读操作时候,它会带着结构体resp这个通道,进入到读通道reads去,拥有state这个协程的通道从读通道reads中响应请求,然后把数据存入resp通道去,然后协程A再从resp通道中拿回结果
- 同理协程B想进行写操作,也是如此