有没有使用消息建模共享状态的方法?

问题描述:

所以目前我在编写“正确的”golang时遇到了一个非常现实的问题。我有一个对象(为了简单起见,我们可以把它看作一个map [string]字符串),我希望它在多个gortuines之间保持“共享”状态。有没有使用消息建模共享状态的方法?

目前的实施是这样的:

//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 

虽然这确实做的工作是相当难看实现由GO标准,鼓励利用信息建模并发。

有没有简单的方法来使用我公然不知道的消息建模共享状态?或者我是否*在这种情况下使用互斥体?

+2

如果您只需共享一个资源,那么使用互斥锁是首选方式。在这种情况下,消息传递在我看来并没有什么意义。 – squiguy

您不用“使用消息建模共享状态”,而是使用消息而不是共享状态,这需要根据不同的基础设计应用程序。这通常不是将互斥体重写为频道的问题,而是一种完全不同的实现方法,并且该方法不适用于需要同步操作的所有场景。如果共享映射是适合您情况的最佳方法,那么互斥量是同步访问的正确方法。

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

+0

那么,这是一种我一般来说喜欢的设计(即每个线程都有其独立版本的数据,并在每次更改时都会接收更新)。我正在考虑的做法是让两种方式都可以让状态持有者在发生配置更改时接收消息,然后向使用状态的每个人发送消息。 – George

+0

在这种类型的模式下,是否有一个很好的代码示例?(基本上就是你描述的,但消费者也可以写信给一个频道来改变配置......或者你碰巧遇到的任何共享状态)......看起来不错但我完全没有意识到它可能存在的明显(不太明显)的缺陷 – George

+0

我手边没有任何示例,谷歌可能会帮助你。重要的是不要将其视为共享状态,而应将其视为发送消息或事件。渠道是一个pub/sub模型,而不是共享模型,并且将它们视为实现共享的一种方式会导致挫败感。想象一下,如果你所有的goroutines在不同的机器上都是独立的进程,如果您使用数据库共享状态,请使用互斥锁。如果您使用消息队列发布/订阅事件,请使用频道。 – Adrian