2017-10-14 161 views
0

這裏是我主要功能的主體;初學者級代碼的死鎖

c := make(chan int) 

go func() { 

    i := <-c 
    i++ 
    time.Sleep(100 * time.Millisecond) 

    c <-i 


}() 

time.Sleep(1 * time.Second) 
go func() { 
    i := <-c 
    i++ 
    time.Sleep(100 * time.Millisecond) 
    c <-i 

}() 

time.Sleep(1 * time.Second) 
fmt.Println(<-c) 

我越來越死鎖error.even我試了waitgroups.hella撕開我的頭髮。

解釋答案對我來說很好。

+2

沒有寫入'c',因此所有3個線程都被鎖定讀取。 – zerkms

+0

我剛剛在println之前加了「c < - 0」,它可以工作,但是當我在第一次去func之前添加它之後,我得到了同樣的死鎖error.wth發生了什麼? –

+0

@KadirSusuz在產生第一個goroutine之前添加寫入操作時,您正在嘗試寫入未緩衝的通道。此操作會阻塞,直到從通道讀取值,但尚未啓動goroutine以從中讀取。解決方案將首先啓動goroutines或創建一個緩衝通道。 – Gavin

回答

0

添加的最後一行之前:

c <- 0 

這樣,你給它可以通過夠程讀取開始工作開始值。您也可以在最後一行前添加到都夠程(發送信道)添加打印夠程數和值:

fmt.Println("goroutine 1 value", i) 

這還可以看到如何在通道中的同一項目的3名可能的消費者的情況過去了。主辦公室很可能會閱讀該頻道,並獲得0。增加Sleep給別人一個機會。用睡眠時間玩,可以獲得不同的結果。

+0

我剛剛在println之前添加了「c < - 0」,它的工作原理,但是當我在第一次去func之前添加它之後,我得到了同樣的死鎖error.wth發生了什麼? –

+0

非常正確 - 因爲那時候沒有可以從頻道讀取的門廳。因此,寫入頻道被阻止,直到有人開始從頻道中讀取。嘗試在起始讀者之間進行書寫。另一種方法:你可以讓你的頻道緩衝 - 這意味着它可以存儲幾個元素。規則是一樣的:如果有新元素的空間,如果沒有空間作家被封鎖,你可以寫信給頻道。如果有讀者,它會讀取元素,從而爲新的元素騰出空間。如何創建緩衝頻道? make(chan int,10)' - 這裏是10 buf len –

1

在寫入之前,您正在閱讀頻道,因此所有事情都會陷入僵局,等待無法完成的閱讀。

在打電話給Printf之前,您可以打c <- 0來打破僵局,但程序可以打印0,1或2.請注意,如果您在開始第一個goroutine之前先發送初始發送,則會出現同樣的問題從另一個方面來說,發送沒有可能的讀取。

如果你說過你正在嘗試做什麼,這將會更容易幫助,因爲它是我無法真正提供任何特定的指針。

+0

「,0是迄今爲止最可能的結果。」 ---這也是我的想法,但在play.golang上是2。在一臺CPU上,機器2更有可能。 – zerkms

+0

在哪裏放置第一次發送,你睡在哪裏將是對單核心機器的主要影響,但是現在誰在運行單核心機器? :P如果你在第一次發送後立即睡眠,在多個內核上變得相當不可預測。 –

+0

我剛剛在println之前添加了「c < - 0」,它可以工作,但是當我在第一次去func之前添加它時,我得到了同樣的死鎖error.wth發生了什麼? –

0

你有一個無緩衝的渠道,這意味着你的工作「同步」我的意思是當使用無緩衝的渠道,你需要一個作家和讀者來實現一些嘗試緩衝渠道,你可以嘗試選擇等待消息。 2 - 在寫入之前,您正在讀取未緩衝的通道,該通道將阻塞,直到寫入操作發生。所以你從一個封閉的渠道中獲得了2位讀者(因爲沒有作家)。