在 Goroutine 中等待管道 io.Copy 時發生死鎖是一個常見的問題。當我們在一個 Goroutine 中等待 io.Copy 的完成時,如果管道沒有被正確地關閉,就會導致死鎖。在這種情況下,Goroutine 會一直在等待數據,而無法繼續執行。解決這個問題的方法是,在 io.Copy 完成後,手動關閉管道,以確保 Goroutine 可以正確結束。 php小編蘋果為你詳細介紹了這個問題的原因和解決方法,希望能幫助你更好地處理這類死鎖狀況。
在下面的程式碼中,對 io.copy
的呼叫永遠不會回傳;它只是無限期地阻塞,導致死鎖。只有當使用 io.pipe
將 io.reader
連接到 os.stdout
io.writer
時,才會發生此行為。但是,我需要使用管道,因為在我的完整程式碼中,我使用io.multiwriter
和io.pipe
s 將一個io.reader
連接到許多需要io.reader
的函數。
func main() { read := strings.newreader("abcdefghij") pipereader, pipewriter := io.pipe() var wg sync.waitgroup wg.add(1) go func() { println("start copy") _, err := io.copy(os.stdout, pipereader) if err != nil { println(err.error()) } println("end copy") wg.done() }() _, err := io.copy(pipewriter, read) if err != nil { println(err.error()) } wg.wait() }
輸出:
Start copy abcdefghij fatal error: all goroutines are asleep - deadlock! goroutine 1 [semacquire]: sync.runtime_Semacquire(0xc0000b0018?) /usr/local/go-faketime/src/runtime/sema.go:62 +0x25 sync.(*WaitGroup).Wait(0x4969c8?) /usr/local/go-faketime/src/sync/waitgroup.go:139 +0x52 main.main() /tmp/sandbox4108076976/prog.go:31 +0x23c goroutine 18 [select]: io.(*pipe).read(0xc0000a6120, {0xc0000b6000, 0x8000, 0xc00009e101?}) /usr/local/go-faketime/src/io/pipe.go:57 +0xb1 io.(*PipeReader).Read(0x10?, {0xc0000b6000?, 0xc00009e1e0?, 0x4f75a0?}) /usr/local/go-faketime/src/io/pipe.go:136 +0x25 io.copyBuffer({0x496aa8, 0xc00009e1e0}, {0x4969a8, 0xc0000a4018}, {0x0, 0x0, 0x0}) /usr/local/go-faketime/src/io/io.go:427 +0x1b2 io.Copy(...) /usr/local/go-faketime/src/io/io.go:386 os.genericReadFrom(0xb000000006018ab?, {0x4969a8, 0xc0000a4018}) /usr/local/go-faketime/src/os/file.go:162 +0x67 os.(*File).ReadFrom(0xc0000a4008, {0x4969a8, 0xc0000a4018}) /usr/local/go-faketime/src/os/file.go:156 +0x1b0 io.copyBuffer({0x496a28, 0xc0000a4008}, {0x4969a8, 0xc0000a4018}, {0x0, 0x0, 0x0}) /usr/local/go-faketime/src/io/io.go:413 +0x14b io.Copy(...) /usr/local/go-faketime/src/io/io.go:386 main.main.func1() /tmp/sandbox4108076976/prog.go:18 +0x71 created by main.main /tmp/sandbox4108076976/prog.go:16 +0x1d3
這裡是程式碼的遊樂場連結:https://goplay.tools/snippet/70ubgiz8ftv
有沒有辦法在保留 io.pipe
的同時避免死鎖?
完成後關閉管道的寫入端:
_, err := io.Copy(pipeWriter, read) pipeWriter.Close() if err != nil { println(err.Error()) }
否則,讀者端將無限期地等待。
以上是在 Goroutine 中等待管道 io.Copy 時發生死鎖的詳細內容。更多資訊請關注PHP中文網其他相關文章!