【go从零单排】Stateful Goroutines(有状态的 goroutines)

🌈Don't worry , just coding!
内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。

📗概念

在 Go 中,有状态的 goroutines(Stateful Goroutines)是指那些能够保留状态信息的 goroutines。这种设计模式通常用于需要在多个调用之间维护状态的场景,例如处理请求、管理连接、维护计数器等。

💻代码

go 复制代码
package main

//导入math/rand 用于生成随机数。
//sync/atomic 提供原子操作的支持。
import (
	"fmt"
	"math/rand"
	"sync/atomic"
	"time"
)

// readOp 结构体用于表示读操作,包含一个键 key 和一个响应通道 resp。
type readOp struct {
	key  int
	resp chan int
}

// readOp 结构体用于表示读操作,包含一个键 key 和一个响应通道 resp。
type writeOp struct {
	key  int
	val  int
	resp chan bool
}

func main() {
	//声明两个无符号整型变量 readOps 和 writeOps,用于计数读写操作。
	var readOps uint64
	var writeOps uint64
	//创建两个通道 reads 和 writes,分别用于接收读操作和写操作。
	reads := make(chan readOp)
	writes := make(chan writeOp)

	go func() {
		//启动一个 goroutine,维护一个状态 state,这是一个映射,存储键值对。
		var state = make(map[int]int)
		for {
			//使用 select 语句监听 reads 和 writes 通道:
			select {
			//如果接收到读操作,从 state 中读取对应的值并通过 resp 通道返回。
			case read := <-reads:
				read.resp <- state[read.key]
			//如果接收到写操作,将值写入 state 中,并通过 resp 通道返回操作成功的信号。
			case write := <-writes:
				state[write.key] = write.val
				write.resp <- true
			}
		}
	}()
	//启动 100 个 goroutine
	for r := 0; r < 100; r++ {
		go func() {
			for {
				//创建一个随机键的 readOp 实例并发送到 reads 通道。
				read := readOp{
					key:  rand.Intn(5),
					resp: make(chan int)}
				reads <- read
				<-read.resp
				//创建一个随机键的 readOp 实例并发送到 reads 通道。
				atomic.AddUint64(&readOps, 1)
				//每次循环后休眠 1 毫秒。
				time.Sleep(time.Millisecond)
			}
		}()
	}
	//启动 10 个 goroutine
	for w := 0; w < 10; w++ {
		go func() {
			for {
				//创建一个随机键和随机值的 writeOp 实例并发送到 writes 通道。
				write := writeOp{
					key:  rand.Intn(5),
					val:  rand.Intn(100),
					resp: make(chan bool)}
				writes <- write
				<-write.resp
				//等待响应并通过原子操作增加 writeOps 的计数。
				atomic.AddUint64(&writeOps, 1)
				//每次循环后休眠 1 毫秒。
				time.Sleep(time.Millisecond)
			}
		}()
	}

	time.Sleep(time.Second)
	//使用 atomic.LoadUint64 获取最终的读写操作计数并打印。
	readOpsFinal := atomic.LoadUint64(&readOps)
	fmt.Println("readOps:", readOpsFinal)
	writeOpsFinal := atomic.LoadUint64(&writeOps)
	fmt.Println("writeOps:", writeOpsFinal)
}
//输出
//readOps: 81299
//writeOps: 8163

有状态的 Goroutines 的特点

  • 状态管理:有状态的 goroutines 可以在其生命周期内维护状态信息,这样它们可以根据之前的操作或输入做出决策。
  • 并发安全:在并发环境中,状态的管理需要确保安全性,通常使用通道、互斥锁或其他同步机制来保护共享状态。
  • 封装性:将状态和行为封装在 goroutine 内部,使得外部无法直接访问状态,从而增强了模块化和封装性。

🔍理解

  • 并发读写:代码实现了一个简单的并发读写操作,使用通道来协调读写请求。
  • 原子操作:使用 sync/atomic 包中的原子操作来安全地更新读写计数,避免数据竞争。
  • 随机访问:读和写操作都是基于随机生成的键值,使得操作更加多样化。
  • 无锁设计:通过通道和 goroutine 的组合,避免了传统的锁机制,简化了并发控制。

💪无人扶我青云志,我自踏雪至山巅。

相关推荐
金銀銅鐵38 分钟前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(上)
java·后端·ai编程
catchadmin41 分钟前
PHP 8.7 协程新提案 让跨协程代码共享请求身份
开发语言·php
念何架构之路1 小时前
go-grpc设计思想
开发语言·后端·golang
system_error_x2 小时前
SpringBoot 集成 Thymeleaf 简洁入门
java·spring boot·后端
酷炫码神2 小时前
Day 10|Pinia 状态管理:把散落在各组件的数据,收进一个全局仓库
android·开发语言·javascript
microrain2 小时前
SagooIoT 的缓存换后端只改一行配置,文件后端连 Redis 都不需要
物联网·缓存·golang·sagooiot
Elastic 中国社区官方博客3 小时前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn1883 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn3 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
喵了几个咪4 小时前
GoWind ShortPlay 深度拆解:三服务 BFF + Core,一条请求的完整工程链路
golang·gowind