有没有一种方法可以使用消息来建模共享状态?

huangapple go评论76阅读模式
英文:

Is there a way to model shared state using messages?

问题

目前我在编写“正确”的 Golang 代码时遇到了一个非常真实的问题。我有一个对象(为了简单起见,我们可以将其视为 map[string]string),我希望它在多个 goroutine 之间保持一个“共享”状态。

目前的实现大致如下:

// 在 shared_state.go 中

var sharedMap map[string]string = make(map[string]string)
var mutex sync.RWMutex = sync.RWMutex{}

func Add(k string, v string) bool {
mutex.Lock()
if _, exists := sharedMap[k]; exists {
mutex.Unlock()
return false
}
sharedMap[k] = v
mutex.Unlock()
return true
}
// 其他访问、修改等方法

虽然这样做确实可以完成任务,但按照 Go 的标准来说,这是一个相当丑陋的实现,Go 鼓励使用消息来建模并发。

是否有简单的方法可以使用消息来建模共享状态,而我却毫不知情?或者在这种情况下,我是否被迫使用互斥锁?

英文:

So currently I've come upon a very real problem in writing "correct" golang. I have an object (for the sake of simplicity lets think of it as a map[string]string) and I want it to hold a "shared" state between multiple gortuines.

Currently the implementation goes something like this:

//Inside shared_state.go

var sharedMap    map[string]string = make(map[string]string)
var mutex       sync.RWMutex     = sync.RWMutex{}

func Add(k string, v string) bool {
    mutex.Lock()
    if _, exists := sharedMap[k]; exists {
        mutex.Unlock()
        return false
    }
    tokenMap[k] = v
    mutex.Unlock()
    return true
}
//Other methods to access, modify... etc

Whilst this does do the job is quite an ugly implementation by go standards, which encourage modeling concurrency using message.

Are there easy ways of modeling shared state using messages that I am blatantly unaware of ? Or am I forced to use mutexes in this kind of cases ?

答案1

得分: 2

你不是“使用消息来模拟共享状态”,而是使用消息“代替”共享状态,这需要基于不同的基本原理设计应用程序。通常情况下,并不是将互斥锁重写为通道,而是采用完全不同的实现方法,这种方法并不适用于所有需要同步操作的场景。如果共享映射是你的情况下最佳方法,那么互斥锁是同步访问的正确方式。

以我自己的经验为例,我开发过可以在运行时更改配置的应用程序。与其拥有一个共享的Config对象并同步访问它,我为每个主goroutine提供一个通道,它可以接收配置更新。当配置发生变化时,更新会发送给所有的监听器。当监听器收到配置更改时,它可以完成当前操作,然后根据该例程适当的方式处理配置更改-它可能只是更新其本地副本的配置,可能关闭与外部资源的连接并打开新的连接等。我不是共享数据,而是发送和接收事件,这是一种根本不同的设计。

英文:

You don't "model shared state using messages", you use messages instead of shared state, which requires designing the application based on different fundamentals. It is generally not a matter of rewriting a mutex as a channel, but a completely different implementation approach, and that approach won't be applicable to all scenarios where you need to synchronize operations. If a shared map is the best approach for your situation, then a mutex is the correct way to synchronize access to it.

As an example from my own experience, I've developed applications that allow for changing their configuration at runtime. Rather than having a shared Config object and synchronizing access to it, I give each main goroutine a channel on which it can receive configuration updates. When the config changes, the update is sent to all the listeners. When a listener gets a config change, it can complete its current operation, then deal with the config change in whatever way is appropriate to that routine - it may just update its local copy of the config, it may close connections to external resources and open new ones, etc. Instead of sharing data, I'm sending and receiving events, which is a fundamentally different design.

huangapple
  • 本文由 发表于 2017年6月1日 05:28:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/44294959.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定