Golang 中 select 语句中的死锁和默认情况
selectselectselectselect

死锁

在 Golang 中,死锁是一种非常令人头疼的问题。它指的是在程序中的一些 Goroutines 互相等待,导致所有 Goroutines 都无法向前推进。一个常见的死锁例子是两个 Goroutines 相互等待对方完成某个任务。

select
  1. 所有通道都被阻塞,并且没有默认操作。
  2. 所有通道都被阻塞,并且在有默认操作的情况下,未选择默认操作。

以下是一个死锁示例:

package main

import "time"

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)

    go func() {
        for {
            select {
            case <-ch1:
                ch2 <- 1
            }
        }
    }()

    // 这里的 select 语句会导致死锁,因为没有默认情况,且 ch1 和 ch2 都被阻塞
    select {
    case ch1 <- 1:
    case <-ch2:
    }
}
select
selectselect
defaultselect

以下是修改后的示例代码:

package main

import "time"

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)

    go func() {
        for {
            select {
            case <-ch1:
                ch2 <- 1
            }
        }
    }()

    // 这里的 select 语句中添加了一个默认情况,避免了死锁问题
    select {
    case ch1 <- 1:
    case <-ch2:
    default:
    }
}

在上面的示例中,我们添加了一个默认情况。当所有的 case 都被阻塞时,该默认情况就会被执行,避免了死锁问题。

默认情况

select