目錄
問題內容
解決方法
解決方案
首頁 後端開發 Golang Go 程式在 goroutine 工作完成之前退出

Go 程式在 goroutine 工作完成之前退出

Feb 08, 2024 pm 10:57 PM
go語言

Go 程序在 goroutine 工作完成之前退出

php小編小新在這篇文章中將介紹一個關於Go程式的重要問題:在goroutine工作完成之前就退出的情況。在Go語言中,goroutine是一種輕量級的線程,可以並發執行任務。然而,當我們的程式可能在goroutine工作完成之前退出時,我們需要了解如何處理這種情況,以確保我們的程式能夠正確地完成任務。在接下來的內容中,我們將探討這個問題,並提供一些解決方案來解決它。

問題內容

我在了解如何正確封鎖和關閉頻道時遇到問題。我正在啟動任意數量的工作人員,我發現我的主要功能要么在工作人員完成之前退出,要么由於未關閉的通道而掛起。我需要一種更好的方法來阻止工作人員在不退出主通道的情況下讀取通道,然後在完成後優雅地關閉通道以結束循環。我所做的任何嘗試都以僵局告終。

我嘗試了一些方法,包括使用等待群組,但問題仍然存在。我注意到,透過新增 time.sleep,程式按預期工作,但將其註解掉會導致沒有完成任何工作。

time.sleep(time.duration(10 * time.second))
登入後複製

這是一個可運行的範例 https://go.dev/play/p/qhqnj-ajqbi,其中保留了 sleep。這是註解掉睡眠超時的損壞代碼。

package main

import (
    "fmt"
    "sync"
    "time"
)

// some complicated work
func do(num int, ch chan<- int) {
    time.sleep(time.duration(500 * time.millisecond))
    ch <- num
}

func main() {

    results := make(chan int)

    // for some number of required complicated work
    for i := 0; i < 53; i++ {
        go do(i, results)
    }

    var wg sync.waitgroup

    // start 3 workers which can process results
    for i := 0; i < 3; i++ {
        wg.add(1)
        go func(id int) {
            defer wg.done()
            worker(id, results)
        }(i)
    }

    // handle closing the channel when all workers complete
    go func() {
        wg.wait()
        close(results)
    }()

    //time.sleep(time.duration(10 * time.second))

    fmt.println("donezo")
}

// process the results of do() in a meaningful way
func worker(id int, ch <-chan int) {
    fmt.println("starting worker", id)

    for i := range ch {
        fmt.println("channel val:", i)
    }
}
登入後複製

我還嘗試將 defer wg.done() 移動到 worker() func 內部,但這是同樣的問題,並且在沒有睡眠的情況下無法工作。

// process the results of do() in a meaningful way
func worker(wg *sync.WaitGroup, id int, ch <-chan int) {
    fmt.Println("starting worker", id)

    defer wg.Done()

    for i := range ch {
        fmt.Println("channel val:", i)
    }
}
登入後複製

我是否選擇了錯誤的範式,或者我只是使用了錯誤的範式?

解決方法

我最初問「我可以對我的程式碼進行一些小調整來使其工作嗎?還是我必須重新考慮這個問題?」我發現的答案是,是的,有是一個小調整。

我必須學習一個關於通道的有趣的基本概念:您可以從封閉的通道中讀取數據,即排空通道。正如我最初的範例中提到的range 永遠不會終止,因為我找不到關閉通道的好地方,即使當我以其他創造性的方式強制它時,程式也會表現出不良行為

  • 未處理完頻道內的所有內容而退出
  • 死鎖或在封閉通道上發送

這是因為「真實」程式碼的細微差別,其中處理通道內容所需的時間比填充所需的時間更長頻道和事物不同步。

由於我的發送者中沒有明確的實用方法來關閉通道(99% 的通道教程中都建議這樣做),因此當您有多個工作人員正在讀取通道並且工作人員不知道時,透過goroutine 在main 中執行此操作實際上是可以接受的其中哪些讀取了最後一個值。

解決方案

我將工作人員包裝在自己的sync.waitgroup 中,並使用worker.wait()阻止程序退出,從而允許工作“完成” ”。當沒有更多數據要發送時,我獨立地close() 通道,即我通過使用他們自己的等待組等待編寫者完成來阻止。close為範圍循環提供了一個終止情況,因為當返回通道的預設值時,即到達通道結束時返回eof 類型,它將結束。阻塞交會通道沒有終點,直到它被關閉。

我對此的看法是,如果您不知道將並行推送多少個值,則 go 無法知道無緩衝通道的長度,因為它正在範圍內,直到您關閉它。 。由於關閉,它表示讀取剩餘的任何內容,直到終止值或結束。 workers.wait() 會阻塞,直到完成。

已解決操作的範例 https://www.php.cn/link/2bf0ccdbb4d3ebbcb990af74bd78c658

讀取關閉通道的範例 https://www.php.cn/link/d5397f1497b5cdaad7253fdc92db610b

輸出

filling 0
filling 1
filling 2
filling 3
filling 4
filling 5
filling 6
filling 7
filling 8
filling 9
closed
empyting 0
empyting 1
empyting 2
empyting 3
empyting 4
empyting 5
empyting 6
empyting 7
empyting 8
empyting 9
登入後複製

以上是Go 程式在 goroutine 工作完成之前退出的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

golang 如何使用反射存取私有欄位和方法 golang 如何使用反射存取私有欄位和方法 May 03, 2024 pm 12:15 PM

golang 如何使用反射存取私有欄位和方法

golang函數動態建立新函數的技巧 golang函數動態建立新函數的技巧 Apr 25, 2024 pm 02:39 PM

golang函數動態建立新函數的技巧

Go語言中的效能測試與單元測試的差異 Go語言中的效能測試與單元測試的差異 May 08, 2024 pm 03:09 PM

Go語言中的效能測試與單元測試的差異

Golang技術在設計分散式系統時應注意哪些陷阱? Golang技術在設計分散式系統時應注意哪些陷阱? May 07, 2024 pm 12:39 PM

Golang技術在設計分散式系統時應注意哪些陷阱?

Golang技術在機器學習中使用的函式庫和工具 Golang技術在機器學習中使用的函式庫和工具 May 08, 2024 pm 09:42 PM

Golang技術在機器學習中使用的函式庫和工具

Golang技術在行動物聯網開發中的作用 Golang技術在行動物聯網開發中的作用 May 09, 2024 pm 03:51 PM

Golang技術在行動物聯網開發中的作用

golang函數命名約定的演變 golang函數命名約定的演變 May 01, 2024 pm 03:24 PM

golang函數命名約定的演變

golang可變參數是否可以用於函數傳回值? golang可變參數是否可以用於函數傳回值? Apr 29, 2024 am 11:33 AM

golang可變參數是否可以用於函數傳回值?

See all articles