Go的并发 | 青训营笔记

100 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天。

一、重点内容概括

  • GoRoutine
  • Channel
  • 线程同步

二、详细知识点

Goroutine

  GoRoutine是一种轻量化的线程,由GoLang运行时调度,同一个程序中的所有 goroutine 共享同一个地址空间。只需在调用函数前添加go关键字便可创建一个 goroutine 来运行该函数:

func hello(s string) {
	fmt.Println("Hello ", s, "!")
}
func main() {
	animal := []string{"可爱的狗狗", "猫猫", "熊熊", "鼠鼠(努力学习版)", "鲨鲨", "鼠鼠(仓鼠版)"}
	for _, name := range animal {
		go hello(name)
	}
	time.Sleep(time.Second)
}

线程通信

  GoLang建议“通过通信实现共享内存”而不是“通过共享内存进行通信”,因为使用共享内存进行通信难免需要枷锁,这回降低程序性能。GoLang 通过“通道”(channel)进行 goroutine之间的通信。

  创建 channel 使用make

ch := make(chan int)        // 无缓冲区双向
ch1 := make(chan int, 2)    // 有缓冲区双向
chi := make(<-chan int)     // 只读
cho := make(chan<- int)     // 只写

  使用<-将数据写入 channel 或从 channel 读取数据,使用range遍历 channel 中的数据

  1. 对于不带缓冲区的通道,接受方获取数据前发送方会阻塞
  2. 对于带缓冲区的通道,缓冲区满后发送方写入数据会导致写入线程阻塞

  通道不再使用后,可通过close()函数来关闭,从而避免通道已空但接收方尝试读取导致阻塞的问题。

  1. 在通道未初始化时关闭、重复关闭、关闭后发送共和发送时关闭会导致 panic

线程同步

  sync包提供了基础的线程同步锁,创建一个互斥锁的方式如下:

var lock sync.Mutex

  该互斥锁使用Lock()Unlock()方法对编辑共享内存的代码块加锁,保证线程同步。

  有时候我们需要在主线程执行到某个位置时开启多个子线程执行其他任务,且在这些子线程全部结束前阻塞主线程,这时我们就需要WaitGroup

var wg sync.WaitGroup

  WaitGroup有三个方法:Add(delta int)用于计数器增加 delta ;Done()用于表示一个线程完成;Wait()用于阻塞主线程。

三、参考资料

本文若有不足之处,欢迎纠正(≧^.^≦)喵~
我的其他笔记,可在掘金或 Github( github.com/DoudiNCer/I… )阅读