【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 的组合,避免了传统的锁机制,简化了并发控制。

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

相关推荐
逻辑驱动的ken5 分钟前
Java高频考点场景题24
java·开发语言·面试·职场和发展·求职招聘
兔小盈15 分钟前
多线程-(五)线程安全之内存可见性
java·开发语言·多线程
REDcker18 分钟前
个人博客网站建设指南 Markdown资产化与静态站选型部署
前端·后端·博客·markdown·网站·资产·建站
Supersist36 分钟前
【设计模式03】使用模版模式+责任链模式优化实战
后端·设计模式·代码规范
yaoxin5211231 小时前
400. Java 文件操作基础 - 使用 Buffered Stream I/O 读取文本文件
java·开发语言·python
Fox爱分享1 小时前
字节二面:10亿数据毫秒级查手机尾号后4位,答不出“异构索引”直接挂?
java·后端·面试
折哥的程序人生 · 物流技术专研1 小时前
《Java面试85题图解版(二)》进阶深化上篇:并发编程 + JVM
java·开发语言·后端·面试
Mahir081 小时前
MySQL 数据一致性的基石:三大日志( redo log/undo log/binlog)与两阶段提交(Prepare 阶段和Commit 阶段)深度解密
数据库·后端·mysql·面试
L0CK1 小时前
Redis 内存淘汰策略
后端
2501_931803751 小时前
Go:一门为解决C语言痛点而生的现代语言
c语言·开发语言·golang