2015-12-10 51 views
2

從我對Go調度程序的理解中,Go調度算法是partially preemptive:goroutine開關在goroutine調用函數或阻塞I/O時發生。通道是否爲goroutine調度發送搶佔點?

發送消息到通道時是否發生goroutine切換?

// goroutine A 
ch <- message 
// some additional code without function calls 

// goroutine B 
message := <- ch 

在上面的代碼中,我想在一個ch <- message後的代碼,以在切換到B之前被執行,這是保證?或者B在ch發送消息後立即進行排定?

+0

依賴於運行時的實現細節充滿危險。我會重新考慮你的代碼。 –

+2

很多時候沒有運行時間預防。 Goroutines A和B可能運行在內核預先設置的不同操作系統線程中,或者完全運行在不同的CPU內核上。 – JimB

回答

7

A的通道發送可能會阻塞,此時它會發送給調度程序,並且您不能保證A何時會再次接收控制權。它可能在你對B感興趣的代碼之後。因此即使使用GOMAXPROCS=1,示例代碼也有問題。

後退:搶先發生時是一個實現細節;它在過去發生了變化(函數調用並不總是有搶先機會),並且可能在將來發生變化。根據memory model,如果您的程序依賴於有關代碼執行的事實,那麼該程序在今天碰巧是真實的,但不能保證。如果要阻止B中的某些代碼運行,直到A執行某些操作,則需要找出一種方法來安排使用通道或原語的通道。

正如用戶JimB所指出的那樣,您甚至不需要考慮搶佔來解決示例代碼中的問題。 A和B可以在不同的CPU內核上同時運行,並且在A中發送之後的代碼正在運行時,B中接收到的代碼可以運行。

1

我對語言和運行時的實際理解是,如果沒有你在ch <- message之後和調用goroutine B之前明確阻塞,你不能保證A會在B之前完成或運行。我不知道如何實現它,但是我也不在乎,因爲我接受了面值的門戶抽象。不要依賴程序中的巧合功能。舉個例子,我的建議是將一個通道傳入goroutine A,然後阻止等待接收它,以便序列化A和B.