Go语言编程基础 并发(一)——Go程、信道

柳项明
2023-12-01

1 Go程

Go程(goroutine)是由Go运行时管理的轻量级线程。

# 启动一个Go程并执行f(x, y, z)
go f(x, y, z)

note:f、x、y、z的求值在当前Go程中,而f的执行发生在新的Go程中。
Go程在相同的地址空间中运行,因此在访问共享内存时必须进行同步。

package main
import (
  "fmt"
  "time"
)

func fff(s string)  {
  for i := 0; i < 5; i++{
    fmt.Println(s, i)
  }
}

func main()  {
  go fff("aaa")
  fff("iii")
}

2 信道

信道是带有类型的管道,可以使用信道操作符<-来发送或接收值。

# 将v发送至信道ch
ch <- v 
# 从ch接收值并赋予v
v := <-ch

note:“箭头就是数据流的方向”。

信道在使用前必须先创建。

# 创建信道
ch := make(chan int)

默认情况下,发送与接收操作在另一端准备好之前都会阻塞。这使得Go程在没有显式锁或条件变量的情况下进行同步。

package main

import "fmt"

func sum(s []int, c chan int)  {
  sum := 0
  for _, v := range s {
    sum += v
  } 
  c <- sum
}

func main()  {
    s := []int{7, 2, 8, -9, 4, 0}
    c := make(chan int)
    go sum(s[:len(s)/2], c)
    go sum(s[len(s)/2:], c)
    x, y := <-c, <-c
    fmt.Println(x, y, x + y)
}

3 带缓冲的信道

信道可以带缓冲,将缓冲长度作为第二个参数提供给make来初始化一个带缓冲的信道

ch := make(chan int, 100)

仅当信道的缓冲区填满后,向其发送数据时才会阻塞。当缓冲区为空时,接收方会阻塞。

package main

import "fmt"

func main()  {
  c := make(chan int, 5)
  len := 2
  for i := 0; i < len; i++ {
    c <- i
  }
  for i := 0; i < len; i++ {
    fmt.Println(<-c)
  }
}

学习源:Go 指南

 类似资料: