登录
首页 >  Golang >  Go问答

从不同线程读取值

来源:Golang技术栈

时间:2023-04-10 10:18:21 109浏览 收藏

从现在开始,努力学习吧!本文《从不同线程读取值》主要讲解了golang等等相关知识点,我会在golang学习网中持续更新相关的系列文章,欢迎大家关注并积极留言建议。下面就先一起来看一下本篇正文内容吧,希望能帮到你!

问题内容

我正在用 Go 编写执行大量并行计算的软件。我想从工作线程收集数据,但我不确定如何以安全的方式进行。我知道我可以使用通道,但在我的场景中,它们使它变得更加复杂,因为我必须以某种方式在主线程中同步消息(等到每个线程发送一些东西)。

设想

主线程创建 n 个 Worker实例并work()在 goroutine 中启动它们的方法,以便每个工作人员在自己的线程中运行。每隔 10 秒,主线程应该从工作人员那里收集一些简单的值(例如迭代计数)并打印一个综合统计信息。

从工人那里读取值是否安全?主线程将只读取值,每个单独的线程将写入它自己的值。如果值在读取时相差几纳秒就可以了。

关于如何以简单的方式实现这一点的任何其他想法?

正确答案

在 Go 中,如果至少有一个访问是写入,则没有同步的多个 goroutine 的并发访问是不安全的。您的案例符合列出的条件,因此您必须使用某种同步,否则行为将是未定义的。

如果 goroutine(s) 想要将值发送给另一个,则使用通道。您的情况并非完全如此:您不希望您的工作人员每 10 秒发送一次更新,您希望您的主 goroutine每 10 秒 获取 一次状态。

所以在这个例子中,我只是用一个sync.RWMutex: 来保护数据,当工作人员想要修改这些数据时,他们必须获得一个写锁。当主 goroutine 想要读取这些数据时,它必须获取一个读锁。

一个简单的实现可能如下所示:

type Worker struct {
    iterMu sync.RWMutex
    iter   int
}

func (w *Worker) Iter() int {
    w.iterMu.RLock()
    defer w.iterMu.RUnlock()
    return w.iter
}

func (w *Worker) setIter(n int) {
    w.iterMu.Lock()
    w.iter = n
    w.iterMu.Unlock()
}

func (w *Worker) incIter() {
    w.iterMu.Lock()
    w.iter++
    w.iterMu.Unlock()
}

使用这个例子Worker,主 goroutine 可以使用 获取迭代Worker.Iter(),worker 本身可以随时使用Worker.setIter()或更改/更新迭代Worker.incIter(),而无需任何额外的同步。通过正确使用Worker.iterMu.

或者,对于迭代计数器,您也可以使用该sync/atomic包。如果你选择这个,你只能使用atomic包的函数读取/修改迭代计数器,如下所示:

type Worker struct {
    iter int64
}

func (w *Worker) Iter() int64 {
    return atomic.LoadInt64(&w.iter)
}

func (w *Worker) setIter(n int64) {
    atomic.StoreInt64(&w.iter, n)
}

func (w *Worker) incIter() {
    atomic.AddInt64(&w.iter, 1)
}

文中关于golang的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《从不同线程读取值》文章吧,也可关注golang学习网公众号了解相关技术文章。

声明:本文转载于:Golang技术栈 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>