SoFunction
Updated on 2025-03-05

Waiting and deadlock usage of golang coroutine

Directly upload the code:

1. The first case

Without select{}, the main main thread will not wait for the coroutine to run, resulting in the coroutine not getting a chance to run.

You are requesting eventual scheduling (using the two go statements)

of two goroutines and then you exit main without giving the scheduler

a chance to do anything.

With select, the program runs normally.

package main
import (
 "fmt"
        "time"
)
func main() {
 go func1()
 go func2()
 select{}
}
func func1() {
       for{
     ("here1")
            (10 * )
        }
}
func func2() {
       for{
    ("here2")
           (10 * )
       }
}

2. Coroutine has the opportunity to run

But deadlock will occur, fatal error: all goroutines are sleep - deadlock!

The goroutine executing func1 exited, ditto for func2. The main goroutine is blocked with no hope to recover while no other goroutine can be scheduled.

package main
import (
 "fmt"
 //"time"
)
func main() {
 go func1()
 go func2()
 select {
 }
}
func func1() {
 ("here1")
}
func func2() {
 ("here2")
}

3. The third situation is normal operation

package main
import (
 "fmt"
)
var c = make(chan int, 2)
func main() {
 go func1()
 go func2()
 <-c
 <-c
 ("ok")
}
func func1() {
 ("here1")
 c <- 1
}
func func2() {
 ("here2")
 c <- 1
}

4. Another way to achieve the above purpose:

  var wg 
    var urls = []string{
            "/",
            "/",
            "/",
    }
    for _, url := range urls {
            // Increment the WaitGroup counter.
            (1)
            // Launch a goroutine to fetch the URL.
            go func(url string) {
                    // Decrement the counter when the goroutine completes.
                    defer ()
                    // Fetch the URL.
                    (url)
            }(url)
    }
    // Wait for all HTTP fetches to complete.
    ()

Supplement: Analysis of deadlock in golang

Golang's summary of channel deadlock situation and solutions

Read the deadlock of the empty channel directly

When there is no data in a channel and it is read directly, a deadlock occurs:

func main() {
    q := make(chan int, 2)
    <-q
}

Error prompt:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:

()

/home/erick/Desktop/Book/Parallel/:159 +0x4d

exit status 2

In the above code, a channel with 2 capacity is created, and a deadlock occurs when reading directly.

Fixed solution, use the select method to block, place the default processing method in the default:

func main() {
    q := make(chan int, 2)
    select {
    case v := <-q:
        (v)
    default:
        ("nothing in channel")
    }
}

Output:

nothing in channel

Deadlock caused by excessive data writing

Writing data exceeds the channel's capacity, which can also cause deadlocks:

func main() {
    q := make(chan int, 2)
    q <- 1
    q <- 2
    q <- 3
}

Solution, like the way to write, use the select method to block, put the default handling method in the default:

func main() {
    q := make(chan int, 2)
    q <- 1
    q <- 2
    select {
    case q <- 3:
        ("ok")
    default:
        ("wrong")
    }
}

Write data to the closed channel

This causes not deadlocks, but panic.

func main() {
    q := make(chan int, 2)
    close(q)
    q <- 1
}

Code error:

panic: send on closed channel

goroutine 1 [running]:

()

/home/erick/Desktop/Book/Parallel/:154 +0x63

exit status 2

Solution: Only do not write data to the closed channel. . . .

However, data can be read from the already closed channel:

func main() {
    q := make(chan int, 3)
    q <- 1
    q <- 2
    q <- 3
    close(q)
    for v := range q {
        (v)
    }

Let's start explaining the reading and writing of goroutine

package main
import "fmt"
func main() {
 c:=make(chan string)
 go func() {
  c<-"hello"
 }()
 (<-c)
}

The above is correct

package main
import "fmt"
func main() {
 c:=make(chan string)
 (<-c)
 go func() {
  c<-"hello"
 }()
}

The above is wrong, and a deadlock will occur because the program will block (<-c) and will not be executed downward. There was a blockage on this line so that the following code had no chance to execute. Therefore, it can be summarized that writing is before reading and only after writing is completed can the read operation be read.

Summarize:

The above-mentioned deadlock refers to the situation that occurs in the main thread of the program. If the above-mentioned situation occurs in a non-main thread, the read or write situation will be blocked, rather than a deadlock.

In fact, blocking situations eliminate the step of locking, but instead are more conducive to code writing, and blocking should be used reasonably. .

The above is personal experience. I hope you can give you a reference and I hope you can support me more. If there are any mistakes or no complete considerations, I would like to give you advice.