2017-10-13 70 views
-1

我知道這是不對的如何使發送消息到通道的確定順序是正確的

func e6() { 
    c1 := make(chan struct{}, 1) 
    <-c1     
    go func() {   
     c1 <- struct{}{} 
    }() 
} 

,這是正確的

func e6() { 
    c1 := make(chan struct{}, 1) 
    go func() {   //statement1 
     c1 <- struct{}{} 
    }() 
    <-c1  //statement2 
} 

既然我們不能假設語句1和語句2的順序在正確的例子中,如果statement2在statement1之前執行,在這種情況下,正確的例子看起來像是錯誤的例子,但爲什麼這樣做是正確的呢?感謝您的幫助。

回答

2

實際上,這是在您產生goroutine之後會發生的事情:goroutine首先被執行並且通道被填充以便您可以立即從中讀取(<-c1)。或者read語句首先被執行,但由於沒有任何可讀的通道,所以它會一直等到某些內容可以被讀取(「它阻止」)。現在goroutine調度程序開始執行,注意到兩個goroutine塊之一,它「終於」執行另一個goroutine,它填充通道並退出,使得阻塞goroutine成爲唯一的剩餘,因此它再次獲得執行時間。但是現在通道已經填充,可以讀取通道,通道中的值被讀取爲空,原始的goroutine繼續,結束該功能。

請注意,這是一個有點簡單化,你一定要上夠程讀了。

+0

非常感謝。 –

0

這是錯誤的:

func e6() { 
    c1 := make(chan struct{}, 1) 
    <-c1     
    go func() {   
     c1 <- struct{}{} 
    }() 
} 

因爲執行進入一個僵局。通過在主函數線程中調用<-c1,您將阻止來自開放通道的接收。接收將阻塞,直到它從c1收到一些數據,但沒有進程發送任何數據。假設在c1上發送的goroutine尚未啓動,因爲代碼執行在達到go語句之前被阻止。

在正確執行:

func e6() { 
    c1 := make(chan struct{}, 1) 
    go func() {   //statement1 
     c1 <- struct{}{} 
    }() 
    <-c1  //statement2 
} 

它並沒有重要的語句先運行。如果statement1運行第一,因爲夠程在statement2發送c1c1 <- struct{}{})(在不同的線程中運行)的塊還沒有被執行,並且沒有其它的處理從c1接收數據。這導致整個goroutine阻塞,並執行statement2將執行的主函數線程(請記住,go聲明通常不會阻止)。這一次statement2不會阻止,因爲一些其他進程(statement1)已經準備好與數據通過c1發送。因此這兩個線程繼續完成。

類似的推理可以用於其中statement2執行第一的情況進行描述。

+0

在 「正確執行」 _ 「如果'statement1'先運行,在上'c1'發送了夠程bocks」 _。不,它不會因爲'c1'被緩衝。 – icza

+0

哦..沒有看到.. – abhink

+0

'c1'是緩衝區,但它沒有任何數據,因此,如果語句1先運行,在送C1上的夠程塊 –

相關問題