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

news/2024/11/13 10:57:43/

挪威特罗姆瑟夜景

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

📗概念

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

💻代码

package main//导入math/rand 用于生成随机数。
//sync/atomic 提供原子操作的支持。
import ("fmt""math/rand""sync/atomic""time"
)// readOp 结构体用于表示读操作,包含一个键 key 和一个响应通道 resp。
type readOp struct {key  intresp chan int
}// readOp 结构体用于表示读操作,包含一个键 key 和一个响应通道 resp。
type writeOp struct {key  intval  intresp chan bool
}func main() {//声明两个无符号整型变量 readOps 和 writeOps,用于计数读写操作。var readOps uint64var 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.valwrite.resp <- true}}}()//启动 100 个 goroutinefor 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 个 goroutinefor 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 的组合,避免了传统的锁机制,简化了并发控制。

💪无人扶我青云志,我自踏雪至山巅。
在这里插入图片描述


http://www.ppmy.cn/news/1546339.html

相关文章

【开源免费】基于SpringBoot+Vue.JS课程答疑系统(JAVA毕业设计)

博主说明&#xff1a;本文项目编号 T 070 &#xff0c;文末自助获取源码 \color{red}{T070&#xff0c;文末自助获取源码} T070&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

如何在vscode中安装git详细新手教程

一、安装git后点击vscode中的设置 今天教大家如何在VScode中编写代码后提交到git仓库&#xff0c;如果我们不想切换到git的命令行窗口&#xff0c;可以在VScode中配置git&#xff0c;然后就可以很方便快捷的把代码提交到仓库中。 二、在输入框中输入 git.path &#xff0c;再点…

ESLint 使用教程(三):12个ESLint 配置项功能与使用方式详解

前言 在现代前端开发中&#xff0c;代码质量与一致性是至关重要的&#xff0c;ESLint 正是为此而生的一款强大工具&#xff0c;本文将带您详细了解 ESLint 的配置文件&#xff0c;并通过通俗易懂的方式讲解其主要配置项及其配置方法。此外&#xff0c;我们还将探讨一些高级配置…

京东商品详情,Python爬虫的“闪电战”

在这个数字化的时代&#xff0c;我们每天都在和数据打交道&#xff0c;尤其是电商数据。想象一下&#xff0c;你是一名侦探&#xff0c;需要快速获取京东上某个商品的详细信息&#xff0c;但是没有超能力&#xff0c;怎么办&#xff1f;别担心&#xff0c;Python爬虫来帮忙&…

Java:使用Jackson的jsonPtrExp获取节点值的问题说明

使用Jackson时解析json时&#xff0c;经常会使用jsonPath直接获取某一节点下的值&#xff0c;这种方式非常直观 &#xff0c;例如&#xff1a; { “data”: { "test1": "value1", "test2": null, "test3": 10 } } 以Jackson2.13.5&…

java的JJWT 0.91在jdk21中报错的解决方法

参考了很多其他人的办法&#xff0c;只有这种方式可以解决问题 JSON Web Token&#xff08;缩写 JWT&#xff09; 目前最流行、最常见的跨域认证解决方案&#xff0c;前端后端都需要会使用的东西 如果根据黑马的视频&#xff0c;导入了阿里云OSS的相关依赖&#xff0c;自然不会…

JS事件高级练习题

1、用js实现验证码的获取和验证 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><title>Document</title><style>body {margin: 0;}.v_code {width: 300px;height: 200px;border: 1px solid re…

一学就废|Python基础碎片,常用数据类型

字符串 String 与其他编程语言不同&#xff0c;Python 不直接支持字符串的项赋值。因此&#xff0c;如果需要操作字符串的项&#xff0c;例如交换项&#xff0c;我们必须将字符串转换为列表&#xff0c;并在一系列项赋值完成后进行连接操作。 a "Hello Python" l …