返回介绍

10.5.3 通过 goroutine 共享内存

发布于 2024-08-14 12:50:32 字数 6120 浏览 0 评论 0 收藏 0

本主题的最后一小节说明了如何使用专用的goroutine共享数据。尽管,共享内存是线程间彼此通信的传统方法,但 Go 具有内置的同步功能,允许单个 goroutine 拥有共享数据。这意味着其他 goroutines 必须发送消息给这个拥有共享数据的单独 goroutine,这可以防止数据损坏。这样的 goroutine 叫 监视器 goroutine。这 Go 的术语中,这是通过通信来共享而不是通过共享来通信。

该技术通过使用 monitor.go 源文件来说明,分五部分来介绍。monitor.go 程序使用监视器 goroutine 随机产生数字。

monitor.go 的第一部分如下:

package main

import (
    "fmt"
    "math/rand"
    "os"
    "strconv"
    "sync"
    "time"
)

var readValue = make(chan int)
var writeValue = make(chan int)

readValue 管道用于读取随机数,而 writeValue 管道用于得到新随机数。

monitor.go 的第二段代码如下:

func set(newValue int) {
    writeValue <-newValue
}

func read() int {
    return <-readValue
}

set() 函数的目的是共享变量的值,而 read() 函数的目的是读取已保存变量的值。

monitor.go 程序的第三段代码如下:

func monitor() {
    var value int

    for {
        select {
            case newValue := <-writeValue:
                value = newValue
                fmt.Printf("%d", value)
            case readValue <- value:
        }
    }
}

这个程序的所有逻辑都在这个 monitor() 函数里了。最具体地说,select 语句编排了整个程序的操作。当您有读请求时,read() 函数试图从由 monitor() 函数控制的 readValue 管道读取数据。返回保存在 value 变量中的当前值。另一方面,当您想要修改存储值时,可以调用 set()。往 writeValue 管道写数据也由 select 语句处理。结果就是,不使用 monitor() 函数没人可以处理 value 共享变量。

monitor.go 的第四部分代码如下:

func main() {
    if len(os.Args) != 2 {
        fmt.Println("Please give an integer!")
        return
    }
    n, err := strconv.Atoi(os.Args[1])
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Printf("Going to create %d random numbers.\n", n)
    rand.Seed(time.Now().Unix())
    go monitor()

monitor.go 的最后一段代码如下:

    var w sync.WaitGroup
    for r := 0; r < n; r++ {
        w.Add(1)
        go func() {
            defer w.Done()
            set(rand.Intn(10 * n))
        }()
    }
    w.Wait()
    fmt.Printf("\nLast value: %d\n", read())
}

执行 monitor.go 产生如下输出:

$go run monitor.go 20
Going to create 20 random numbers.
89 88 166 42 149 89 20 84 44 178 184 28 52 121 62 91 31c117 140 106
Last value: 106
$go run monitor.go 10
Going to create 10 random numbers.
30 16 66 70 65 45 31 57 62 26
Last value: 26

个人而言,我更喜欢使用监视器 goroutine 而不是传统的共享内存技术,因为使用监视器 goroutine 的实现更安全,更贴合 Go 的哲学思想

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文