ホームページ  >  記事  >  バックエンド開発  >  最後にスリープしないと出力が表示されないのはなぜですか?

最後にスリープしないと出力が表示されないのはなぜですか?

WBOY
WBOY転載
2024-02-06 11:21:03685ブラウズ

最後にスリープしないと出力が表示されないのはなぜですか?

質問の内容

次のコードは、リンク リスト内の要素を交互に出力する 2 つのゴルーチンの使用を実装しています。ただし、最終時刻が表示されないと印刷結果が表示されないという、かなり奇妙な問題に悩まされています。寝る。理論的には、標準出力にはバッファがありません。誰かがガイダンスを提供できますか?

import (
    "context"
    "fmt"
    "sync"
)

type ListNode struct {
    val  int
    next *ListNode
}

func NewLinkedList() (head *ListNode) {
    var cur *ListNode
    for i := 0; i < 100; i++ {
        if cur == nil {
            cur = &ListNode{val: i}
            head = cur
        } else {
            cur.next = &ListNode{val: i}
            cur = cur.next
        }
    }
    return
}

func main() {
    ll := NewLinkedList()
    wg := sync.WaitGroup{}
    var a = make(chan *ListNode, 1)
    var b = make(chan *ListNode, 1)
    ctx, cancel := context.WithCancel(context.Background())
    worker := func(name string, input, output chan *ListNode) {
        wg.Add(1)
        defer wg.Done()
        for {
            select {
            case n := <-input:
                if n == nil {
                    break
                }
                fmt.Printf("%s: %d\n", name, n.val)
                if n.next != nil {
                    output <- n.next
                } else {
                    cancel()
                    break
                }
            case <-ctx.Done():
                break
            }
        }
    }

    go worker("a", a, b)
    go worker("b", b, a)

    a <- ll
    wg.Wait()
    //time.Sleep(time.Millisecond)
}

正解

2つのGoroutineが開始される前にwaitgroupカウンターがインクリメントされるため、メインGoroutineでwg.Add(1)を呼び出す必要がありますmain( ) wg.Wait() に到達することは有効なシナリオです。カウンタが 0 の場合、wg.Wait() はブロックせず、main() が戻り、したがってアプリケーション全体が終了します:

wg.Add(1)
go worker("a", a, b)
wg.Add(1)
go worker("a", a, b)

(もちろん、 wg.Add(1) をスタッフから削除するところから始まります。)

参照: wg.Add() を配置する場所

###

以上が最後にスリープしないと出力が表示されないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。