Home >Backend Development >Golang >How Can I Control the Execution Order of Goroutines in Go?

How Can I Control the Execution Order of Goroutines in Go?

Susan Sarandon
Susan SarandonOriginal
2024-12-12 16:54:10866browse

How Can I Control the Execution Order of Goroutines in Go?

Understanding Goroutine Execution Order

In a goroutine-based program, the order of execution of goroutines can be unpredictable. This is because goroutines are executed concurrently, and there's no guarantee when or in what order they will complete their tasks.

Consider the following code snippet:

func sum(a []int, c chan int) {
    fmt.Println("summing: ", a)
    total := 0
    for _, v := range a {
        total += v
    }
    c <- total  // send total to c
}

func main() {
    c := make(chan int)

    go sum([]int{1,2,3}, c)
    go sum([]int{4,5,6}, c)

    x := <-c
    fmt.Println(x)
    x = <-c
    fmt.Println(x)
}

In this example, two goroutines are launched to calculate the sums of two integer slices. However, the order in which they are executed and their results are printed is not deterministic. You may observe the output as:

summing:  [4 5 6]
15
summing:  [1 2 3]
6

or

summing:  [1 2 3]
6
summing:  [4 5 6]
15

To synchronize the execution order of goroutines, various approaches can be employed:

Using Blocking Channels:

By using the blocking nature of channels, you can force the main goroutine to wait for the completion of each goroutine before moving on to the next. For instance:

func main() {

    c := make(chan int)

    go sum([]int{1, 2, 3}, c)

    // Blocks until a value is received
    x := <-c
    fmt.Println(x)

    // Execute the next goroutine
    go sum([]int{4, 5, 6}, c)

    x = <-c
    fmt.Println(x)
}

Using Wait Groups:

Another common synchronization technique involves using wait groups. A wait group keeps track of the number of goroutines that are still running and waits for them all to complete before proceeding further. Here's how you can use a wait group in the example above:

func sum(a []int, c chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Println("summing: ", a)
    total := 0
    for _, v := range a {
        total += v
    }
    c <- total // send total to c
}

func main() {

    c := make(chan int)
    wg := new(sync.WaitGroup)

    // Increment the wait group
    wg.Add(1)
    // Launch the first goroutine
    go sum([]int{1, 2, 3}, c, wg)

    // Wait for the first goroutine to complete
    wg.Wait()

    // Increment the wait group again
    wg.Add(1)
    // Launch the second goroutine
    go sum([]int{4, 5, 6}, c, wg)

    // Wait for the second goroutine to complete
    wg.Wait()

    // Close the channel to indicate that no more values will be sent
    close(c)

    // Range over the channel to receive the results
    for theSum := range c {
        x := theSum
        fmt.Println(x)
    }

}

By incorporating synchronization techniques into your code, you gain greater control over the order in which goroutines execute, ensuring that they complete their tasks in the desired sequence.

The above is the detailed content of How Can I Control the Execution Order of Goroutines in Go?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn