2013-03-14 26 views
1

我有兩個(但後來我會是三個)去處理來自遠程服務器(來自ampq通道)的傳入消息的例程。但是因爲他們正在處理相同的數據/狀態,所以我想阻止除正在運行的其他所有例程。如何阻止除了正在運行的所有goroutines

我想出了一個解決方案中使用chan bool每個去例行塊,然後鬆開,代碼如下:

package main 

func a(deliveries <-chan amqp, handleDone chan bool) { 
    for d := range deliveries { 
     <-handleDone  // Data comes always, wait for other channels 
     handleDone <- false // Block other channels 

     // Do stuff with data... 

     handleDone <- true // I'm done, other channels are free to do anything 
    } 
} 

func b(deliveries <-chan amqp, handleDone chan bool) { 
    for d := range deliveries { 
     <-handleDone 
     handleDone <- false 
     // Do stuff with data... 
     handleDone <- true 
    } 
} 

func main() { 
    handleDone := make(chan bool, 1) 
    go a(arg1, handleDone) 
    go b(arg2, handleDone) 
    // go c(arg3, handleDone) , later 

    handleDone <- true // kickstart 
} 

但首次各功能將得到handleDone <- true,他們將被執行。如果我添加另一個第三個函數,事情會變得更加複雜。如何阻止除運行之外的其他所有例程?其他更好的解決方案?

+0

我不認爲你的頻道做你認爲他們做的事,因爲你從來沒有檢查收到的價值。無論如何,使用緩衝通道作爲互斥/信號可能是危險的。改用實際的Mutex。 – JimB 2013-03-15 14:34:22

+0

請注意,它們被稱爲「goroutines」,而不是「go routines」。這是因爲「例程」這個詞可能是指任何程序PL中的任何過程/函數,因此「go routines」聽起來像「Go中的例程」,這使術語的預期意義消失。 – kostix 2013-04-29 07:29:07

回答

2

我很困惑你爲什麼要這樣 - 爲什麼不能在deliveries上獨立處理每條消息?爲什麼有兩個不同的函數處理這些消息?如果每個人都對特定類型的消息負責,那麼您似乎希望一個deliveries接收器調度到該類型的適當邏輯。

但是要回答你的問題,我不認爲每個功能在開始時都會從handleDone獲得true。一個(假設它是a)正在接收從main發送的true;其他(b然後)得到從第一個發送的false。因爲你丟棄了收到的價值,所以你不能說出這個。然後兩者都在運行,並且您正在使用緩衝通道(您可能希望使用make(chan bool)而不是無緩衝的通道),因此會引起混淆,特別是在添加第三個goroutine時。

handleDone <- false實際上並沒有完成任何事情。只要將handleDone上的任何值視爲接力比賽中的接力棒。一旦一個門廳收到這個價值,它就可以做到這一點;當它完成後,它應該將它發送到頻道以將其傳送到下一個goroutine。

+0

感謝您的評論。我已經更改了代碼的某些部分。我刪除了'false's。但它現在變成了一堆,它只是在那裏等着。它只是在兩個go函數的'<-handleDone'中等待。似乎他們並沒有從主體中獲得真實。 – 2013-03-14 20:39:16

+0

什麼是'main'這樣做?它是否已經達到'handleDone < - true'? – 2013-03-14 20:46:34

+0

問題是,'handleDone < - true'之後,'func a()'只是等待'func b()',但是在我的情況下'func b()'根本無法執行。我想要的只是在任何時候,如果其中一個例行程序('a()','b()'等等)正在運行,那麼所有其他程序都應該等待,直到正在運行的程序完成爲止 – 2013-03-14 20:51:57

3

如果您有一個傳入的消息流,並且您有三個監聽該流和處理的goroutine,並且您希望確保一次只運行一個goroutine,則解決方案非常簡單:關閉兩個goroutine 。

您正在旋轉併發並增加複雜性,然後嘗試阻止它們同時運行。最終的結果與單流閱讀器相同,但有很多事情可能出錯。

相關問題