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想进行写操作,也是如此

猜你喜欢

转载自www.cnblogs.com/Joestar/p/8876524.html
今日推荐