Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana Menghentikan Rutin Pergi dengan Anggun: Panduan Mengelakkan Kebuntuan dan Proses Tidak Bertindak Balas?

Bagaimana Menghentikan Rutin Pergi dengan Anggun: Panduan Mengelakkan Kebuntuan dan Proses Tidak Bertindak Balas?

Linda Hamilton
Linda Hamiltonasal
2024-10-28 14:11:02536semak imbas

 How to Gracefully Stop a Go Routine: A Guide to Avoiding Deadlocks and Unresponsive Processes?

Cara Menghentikan Rutin Pergi dengan Anggun

Dalam Go, goroutine memberikan keselarasan ringan, tetapi mungkin mencabar untuk menamatkannya dengan anggun. Soalan ini menangani keperluan untuk menghantar isyarat kepada goroutine untuk menghentikan pelaksanaannya.

Kod yang disediakan menunjukkan percubaan untuk menghentikan goroutine dengan menetapkan bendera boolean (terlaluLambat) kepada benar. Walau bagaimanapun, pendekatan ini bermasalah kerana membaca daripada saluran menyekat goroutine.

Penyelesaian 1: Menggunakan Saluran Tambahan

Penyelesaian melibatkan penggunaan saluran kedua (Terlalu Lewat) untuk menyampaikan isyarat berhenti. Saluran ini kekal terbuka walaupun goroutine tidak membaca secara aktif daripadanya.

<code class="go">func main() {
    tooLate := make(chan struct{}) // Unbuffered channel for stop signal
    proCh := make(chan string)

    go func() {
        for {
            fmt.Println("working")
            time.Sleep(1 * time.Second)
            select {
            case <-tooLate:
                fmt.Println("stopped")
                return
            case proCh <- "processed": // Non-blocking send
            default: // Allows the goroutine to continue without blocking
            }
            fmt.Println("done here")
        }
    }()

    select {
    case proc := <-proCh:
        fmt.Println(proc)
    case <-time.After(1 * time.Second):
        fmt.Println("too late")
        close(tooLate) // Signal to goroutine to stop
    }

    time.Sleep(4 * time.Second)
    fmt.Println("finish\n")
}</code>

Dalam penyelesaian ini, apabila had masa tamat, saluran tooLate ditutup, yang menyebabkan goroutine keluar dari pernyataan pilih penyekatnya dan kembali.

Penyelesaian 2: Menggunakan sync.Cond

Sebagai alternatif, anda boleh menggunakan jenis sync.Cond untuk melaksanakan mekanisme isyarat yang lebih canggih. Berikut ialah contoh:

<code class="go">func main() {
    var stopped bool
    cond := sync.NewCond(new(sync.Mutex))

    go func() {
        for {
            cond.L.Lock()
            defer cond.L.Unlock()

            if stopped {
                fmt.Println("stopped")
                return
            }
            fmt.Println("working")
            cond.Wait() // Wait for the signal to stop
        }
    }()

    time.Sleep(1 * time.Second)
    cond.Signal() // Send the stop signal

    time.Sleep(4 * time.Second)
    fmt.Println("finish\n")
}</code>

Dengan pendekatan ini, goroutine menunggu pada kaedah cond.Tunggu() sehingga ia menerima isyarat daripada cond.Signal().

Atas ialah kandungan terperinci Bagaimana Menghentikan Rutin Pergi dengan Anggun: Panduan Mengelakkan Kebuntuan dan Proses Tidak Bertindak Balas?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn