前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Go程序例子(45):Stateful Goroutines

Go程序例子(45):Stateful Goroutines

原创
作者头像
用户11078756
发布2024-12-19 10:09:57
发布2024-12-19 10:09:57
8800
代码可运行
举报
文章被收录于专栏:go程序例子go程序例子
运行总次数:0
代码可运行

在前一个示例中,我们使用了显式锁定和互斥锁来同步多个 goroutines 之间对共享状态的访问。另一个选择是使用 goroutines 和通道的内建同步功能来实现相同的结果。这种基于通道的方法与 Go 的理念一致,即通过通信来共享内存,并且每个数据片段只能由一个 goroutine 拥有。

代码语言:go
复制
package main

import (
    "fmt"
    "math/rand"
    "sync/atomic"
    "time"
)
// 在这个例子中,我们的状态将由单个 goroutine 拥有。这将保证数据在并发访问时不会被损坏。为了读取或写入这个状态,其他 goroutine 将向拥有状态的 goroutine 发送消息,并接收相应的回复。这些 readOp 和 writeOp 结构体封装了这些请求,以及拥有 goroutine 响应请求的方式。
type readOp struct {
    key  int
    resp chan int
}
type writeOp struct {
    key  int
    val  int
    resp chan bool
}

func main() {
	// 像以前一样,我们将统计我们执行了多少个操作。
    var readOps uint64
    var writeOps uint64
	// 读取和写入通道将被其他 goroutine 用来分别发出读取和写入请求。
    reads := make(chan readOp)
    writes := make(chan writeOp)
	// 这是拥有状态的 goroutine,状态是一个像前面例子中的 map,但现在是该有状态 goroutine 私有的。这个 goroutine 会重复地在读取和写入通道上进行选择,响应到达的请求。响应的执行过程是,首先执行请求的操作,然后通过响应通道 resp 发送一个值,表示操作成功(在读取操作的情况下,还会返回期望的值)。
    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
            }
        }
    }()
	// 这将启动 100 个 goroutine,通过读取通道向拥有状态的 goroutine 发出读取请求。每个读取操作需要构造一个 readOp,将其发送到读取通道,然后通过提供的 resp 通道接收结果。
    for r := 0; r < 100; r++ {
        go func() {
            for {
                read := readOp{
                    key:  rand.Intn(5),
                    resp: make(chan int)}
                reads <- read
                <-read.resp
                atomic.AddUint64(&readOps, 1)
                time.Sleep(time.Millisecond)
            }
        }()
    }
	// 我们也启动了 10 个写入操作,使用类似的方法。
    for w := 0; w < 10; w++ {
        go func() {
            for {
                write := writeOp{
                    key:  rand.Intn(5),
                    val:  rand.Intn(100),
                    resp: make(chan bool)}
                writes <- write
                <-write.resp
                atomic.AddUint64(&writeOps, 1)
                time.Sleep(time.Millisecond)
            }
        }()
    }
	// 让 goroutines 工作一秒钟。
    time.Sleep(time.Second)
	// 最后,捕获并报告操作计数。
    readOpsFinal := atomic.LoadUint64(&readOps)
    fmt.Println("readOps:", readOpsFinal)
    writeOpsFinal := atomic.LoadUint64(&writeOps)
    fmt.Println("writeOps:", writeOpsFinal)
}

运行我们的程序显示,基于 goroutine 的状态管理示例总共完成了大约 90,000 次操作。

代码语言:javascript
代码运行次数:0
复制
➜ go run stateful-goroutines.go                       
readOps: 81924
writeOps: 8248

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档