📜  高朗 | Select 语句中的死锁和默认情况

📅  最后修改于: 2021-10-25 02:41:23             🧑  作者: Mango

在 Go 语言中,select 语句就像一个 switch 语句,但是在 select 语句中,case 语句是指通信,即通道上的发送或接收操作。

句法:

select{

case SendOrReceive1: // Statement
case SendOrReceive2: // Statement
case SendOrReceive3: // Statement
.......
default: // Statement

在本文中,我们将学习如何使用默认情况来避免死锁。但首先,我们了解什么是死锁?

死锁:当您尝试从通道读取或写入数据但通道没有值时。因此,它会阻止 goroutine 的当前执行并将控制权传递给其他 goroutine,但是如果没有其他 goroutine 可用或由于这种情况其他 goroutine 正在休眠,程序将崩溃。这种现象称为死锁。如下例所示:

例子:

// Go program to illustrate
// how deadlock arises
package main
  
// Main function
func main() {
  
    // Creating a channel
    // Here  deadlock arises because
    // no goroutine is writing
    // to this channel so, the select 
    // statement has been blocked forever
    c := make(chan int)
    select {
    case <-c:
    }
}

输出:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()

为了避免这种情况,我们在 select 语句中使用默认情况。或者换句话说,当程序中出现死锁时,则执行select语句的default case来避免死锁。如下例所示,我们在 select 语句中使用 default case 来避免死锁。

例子:

// Go program to illustrate how to resolve
// the deadlock problem using the default case
package main
  
import "fmt"
  
// Main function
func main() {
  
    // Creating a channel
    c := make(chan int)
    select {
    case <-c:
    default:
        fmt.Println("!.. Default case..!")
    }
}

输出:

!.. Default case..!

当 select 语句只有 nil 通道时,您也可以使用 default case。如下例所示,通道c为nil,所以如果这里的default case不可用,则执行default case,那么程序将永远阻塞并产生死锁。

例子:

// Go program to illustrate
// the execution of default case
package main
  
import "fmt"
  
// Main function
func main() {
  
    // Creating a channel
    var c chan int
  
    select {
    case x1 := <-c:
        fmt.Println("Value: ", x1)
    default:
        fmt.Println("Default case..!")
    }
}

输出:

Default case..!