2017-05-31 46 views
1

所以目前我在編寫「正確的」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

回答

1

您不用「使用消息建模共享狀態」,而是使用消息而不是共享狀態,這需要根據不同的基礎設計應用程序。這通常不是將互斥體重寫爲頻道的問題,而是一種完全不同的實現方法,並且該方法不適用於需要同步操作的所有場景。如果共享映射是適合您情況的最佳方法,那麼互斥量是同步訪問的正確方法。

以我自己的經驗爲例,我開發了允許在運行時更改其配置的應用程序。我沒有共享Config對象並同步對它的訪問,而是給每個主要的goroutine一個可以接收配置更新的通道。當配置更改時,更新將發送給所有偵聽器。當一個監聽器獲得配置更改時,它可以完成其當前操作,然後以適合該例程的任何方式處理配置更改 - 它可能只更新其配置的本地副本,可能會關閉與外部資源的連接並打開新的等等。我不是共享數據,而是發送和接收事件,這是一個根本不同的設計。

+0

那麼,這是一種我一般來說喜歡的設計(即每個線程都有其獨立版本的數據,並在每次更改時都會接收更新)。我正在考慮的做法是讓兩種方式都可以讓狀態持有者在發生配置更改時接收消息,然後向使用狀態的每個人發送消息。 – George

+0

在這種類型的模式下,是否有一個很好的代碼示例?(基本上就是你描述的,但消費者也可以寫信給一個頻道來改變配置......或者你碰巧遇到的任何共享狀態)......看起來不錯但我完全沒有意識到它可能存在的明顯(不太明顯)的缺陷 – George

+0

我手邊沒有任何示例,谷歌可能會幫助你。重要的是不要將其視爲共享狀態,而應將其視爲發送消息或事件。渠道是一個pub/sub模型,而不是共享模型,並且將它們視爲實現共享的一種方式會導致挫敗感。想象一下,如果你所有的goroutines在不同的機器上都是獨立的進程,如果您使用數據庫共享狀態,請使用互斥鎖。如果您使用消息隊列發佈/訂閱事件,請使用頻道。 – Adrian

相關問題