簡體   English   中英

理解代碼:通過交流共享資源

[英]Understanding the code : Sharing resources by communicating

我一直在嘗試了解https://golang.org/doc/codewalk/sharemem/中的代碼,盡管我大部分是通過通道傳遞資源,但我無法理解程序在其中運行的無限循環。當輪詢器功能的“輸入”通道(從主函數接收)僅運行3個輪詢器執行例程時,程序如何無限執行輪詢器功能?

我得到StateMonitor具有無限循環的匿名go功能的想法。 但是,如果沒有Poller函數的接收,它就無法更新LogState。 我假設程序無限執行對URL的Get請求。

為了確認我對所了解的內容沒有錯,我通過打開和關閉wifi以查看日志是否更改來測試了該程序。 令我驚訝的是,它確實進行了幾次迭代,但是此后它停止響應我的更改並繼續顯示相同的日志。 那么,這是否意味着程序存在錯誤? 還是我不了解一些基本概念?

當輪詢器功能的“輸入”通道(從主函數接收)僅運行3個輪詢器例程時,程序如何無限執行輪詢器功能?

因此,首先程序創建了兩個輪詢器:

for i := 0; i < numPollers; i++ {
    go Poller(pending, complete, status)
}

然后它將三個資源發送到待處理狀態:

for _, url := range urls {
    pending <- &Resource{url: url}
}

每個輪詢器從未決中讀取並輪詢資源:

for r := range in {
    s := r.Poll()
    status <- State{r.url, s}
    out <- r
}

該代碼似乎可以無限執行,但是通常它阻止從隊列中讀取。 因此,此循環等待下一個值出現。

讓我們虛擬地超越它:

  1. 有兩個Pollers閱讀資源。
  2. 程序將第一個資源發送到隊列。
  3. 其中一個輪詢器獲取資源並開始合並。 另一個等待。
  4. 程序有時會將新資源發送到隊列。
  5. 當第一個輪詢器繁忙時,第二個輪詢器將被解除阻塞並開始輪詢。
  6. 當兩個輪詢器忙時,程序將發送第三個資源並阻塞。
  7. 當一個輪詢器完成時,它將占用最后一個資源並繼續。
  8. 同時,主程序從完整隊列中讀取值。

for r := range in { s := r.Poll() status <- State{r.url, s} out <- r }此代碼如何無限運行? 如果它在“輸入”通道上循環,並且“輸入”從掛起隊列中獲取資源,則它應在幾次迭代后終止。 我認為這正是我不理解的部分。

確切地說, in不會從pending隊列中獲取資源。 in pending隊列。 可以通過調用close來關閉隊列(或通道,我可以互換使用),但是直到未明確關閉它為止,它才被認為是活動的。 從其中讀取的任何內容都會阻塞當前的goroutine,直到給出下一個值為止。 然后,gorotine恢復。

我想您一直在思考通道,就像它們是具有固定數量的元素的數組一樣。 他們不是。 考慮它們像具有無限數量的元素但具有阻塞讀取功能的數組,可能會引發異常(如果您不熟悉該概念,則近似於關閉隊列)。

通道上的發送操作將阻塞,直到接收器可用於同一通道:如果通道上的值沒有接收者,則無法在該通道中放置其他值。 反之亦然:當通道不為空時,通道中不會發送任何新值! 因此,發送操作將一直等到通道再次可用。

另一方面,對某個通道的接收操作會阻塞,直到發送方可用於同一通道為止:如果該通道中沒有值,則接收方將阻塞。

要解除阻塞通道,我們需要無限循環地從通道中提取數據。

這就是為什么程序在無限循環中發送和讀取數據的解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM