2012-12-03 57 views
13

考慮下面的例子漏斗數據:http://play.golang.org/p/owvJ8Oi77S線程安全的方式從多個走程序

func produce(dataChannel chan int) { 
    for i := 0; i < 10; i++ { 
     dataChannel <- i 
    } 
} 

func main() { 
    dataChannel := make(chan int) 

    go produce(dataChannel) 
    go produce(dataChannel) 
    go produce(dataChannel) 

    for i := 0; i < 30; i++ { 
     data := <-dataChannel 
     fmt.Printf("%v ", data) 
    } 
} 

是我的假設,寫從多個去例程通道不安全正確嗎?

有沒有一種常見/慣用的方法來安全地做到這一點?我知道你可以爲產生數據的每個例程創建一個單獨的通道,我只是想知道這是否是最乾淨的解決方案或者是否有其他替代方案。

+2

在這方面關於頻道的唯一特別之處是它們只能關閉一次,關閉頻道後不能發送任何內容。爲了更好地理解這一點,請嘗試修改您的示例,以便覆蓋頻道而不是固定大小,然後才能完成。稍微複雜一點,但這是一件很好理解的事情。 – Dustin

+0

是的,我的主要擔心是從多個例程/線程寫入相同的頻道。我不清楚這樣做是否安全。 – Chris

回答

21

通道是完全線程安全的。他們是公用事業公司之間溝通的正式方式。我看到你的代碼沒有錯。這是Go的美麗。

4

通道旨在在線程之間共享(這是「正在線程安全」的正常含義)。使用渠道意味着你沒有共享記憶,因爲你會冒險的種族危害。所以丹尼爾的回答是正確的:使用渠道,因爲這是他們的目的。

但是請注意,如果存在設計錯誤,則goroutines會創建通信順序進程的網絡,如果有的話,有時可能會死鎖。他們也可以活鎖(同樣的事情,但很忙)。

關於如何避免死鎖/活鎖,有大量知識。其中大部分來自Occam在80年代和90年代流行的時代。 Jeremy Martin(Design Strategy for Deadlock-Free Concurrent Systems),Peter Welch(Higher Level Paradigms)等人有幾個特殊的寶石。