Go的并发

65 阅读3分钟

简介

go语言是一个可以简单实现多核处理的编程语言,使用的协程在kb级别,达到能够实现同时起上w个协程

通过通信来共享资源的Channel

介绍

Channel 是 Go 并发编程的核心工具,用于在协程之间传递数据和协作。通过其阻塞特性和类型安全性,可以实现优雅的协程通信,避免使用锁机制带来的复杂性。

特点

  • 类型安全: 一个 channel 只能传递一种类型的数据(定义时指定)。

  • 双向通信: 协程之间可以通过 channel 发送和接收数据。

  • 阻塞特性: 发送方会阻塞,直到数据被接收。 接收方会阻塞,直到有数据发送到 channel。

  • 无锁机制: 使用 channel,可以实现协程之间的数据共享,而不需要显式加锁。

缓冲与不缓冲的区别

在channel中分为有缓冲和不缓冲

  • 不缓冲: 是一种同步通讯,需要接收方和传输方同时存在,一个数据一个数据的传送,发送端会阻塞,直到接收端能够接受数据,接收端会阻塞,直到发送端能够发送数据。 代码:
ch := make(chan int) // 创建一个传递 int 类型的无缓冲 channel
  • 有缓冲: 可以实现异步通讯,可以在定义缓冲空间中存储数据,不会因为接收端没有准备好而阻塞,也不会因为发送端没准备好而阻塞,只有在缓冲区是否满或者是否空的时候发生阻塞。 代码:
ch := make(chan int, 5) // 创建一个带缓冲区大小为 5 的 channel

实战代码

func CalSquare(){
	src := make(chan int)
	dest := make(chan int 3)
	go func(){
		defer close(src)
		for i := 0;i<10;i++{
		src <- i 
		}
	}()
	go func(){
		defer close(dest)
		for int i := range src{
		dest <-i*i
		}
	}()
	for i :=range dest{
	println(i)
	}
}

通过共享资源来实现通讯

我们在共享资源来实现通讯的时候很容易遇到并发问题,这个时候我们要考虑Lock了

Lock

什么是Lock

Lock 是一种用于协调多个线程或协程对共享资源的访问机制,它通过限制同时访问的线程数量来避免数据竞争。常见的 Lock 类型包括:

  • 互斥锁 (Mutex):保证同时只有一个线程能访问共享资源。
  • 读写锁 (RWLock):允许多个线程同时读取,但写入时需独占。
  • 自旋锁 (Spinlock):线程在等待锁时会持续尝试获取锁,而不是挂起。
  • 递归锁 (ReentrantLock):同一个线程可以多次获得同一把锁而不会死锁。

WaitGroup计数器

计数器: 开启协程+1,执行结束-1,主协程阻塞直到计数器等于0

内置方法

  • Add(delta int) 计数器+delta
  • Done() 计数器-1
  • Wait() 阻塞直到计数器为0

实战代码

func ManyGowait(){
	var wg sync.WaitGroup
	wg.Add(5)	// 这里是看你要起多少个协程,我们这里要起5个协程,所以加5
	for i := 0;i<5 ;i++{
		go func(j int){
			defer wg.Done()	// 每完成一次就减少一个
			hello(j)	// 这里其实是实现了一个打印你好
		}(i)	
	}
	wg.Wait()
}