概述
go并发
- goroutine
- channel
- 缓冲与无缓冲
- 单向与双向
- waitgroup
- 锁机制
- 互斥锁
- 读写锁
goroutine
开启一个协程执行这个函数
go func()
main 的地位相当于主协程,当 main 函数执行完成后,主协程终结,其下的运行着的所有协程也立即退出。
可以使用 time.Sleep 来使 main 阻塞,使其他协程能够有机会运行完全。
channel
信道名 := make(chan 信道类型)
信道是一种队列式的数据结构,遵循先入先出的规则,是连接多个goroutine程序的管道 。
发送和接收两个操作都是用<-运算符。
ch <- x // 发送给信道
x = <-ch // 从信道接受
<-ch // 接受
信道死锁
1.当信道里的数据量等于信道的容量后,此时再往信道里发送数据,就失造成阻塞。
2.当程序一直在等待从信道里读取数据,当不再往信道中写入数据时程序就会陷入死循环。因此在发送完数据后,要手动关闭信道。
关闭信道:close(信道名)
判断信道是否被关闭:x, ok := <-信道名
如果已经被关闭,ok 为 false,若还没被关闭,ok 为true。
select函数
select 语句用于在多个发送/接收信道操作中进行选择。
select {
case 1 := <-信道:
case 2 := <-信道:
default:
}
}
当 select 由多个 case 准备就绪时,将会随机地选取其中之一去执行。只要有一个信道有接收到数据,那么 select 就结束。
缓冲与无缓冲
无缓冲信道
对于无缓冲信道,在接收者未准备好之前,发送操作是阻塞的。
解决方法:
1.使接收者代码在发送者之前执行
注意将接收者代码写在另一个协程里
2.使用缓冲信道
缓冲信道
信道名:= make(chan 信道类型, 信道容量)
信道的容量,可以使用 cap 函数获取 ;信道的长度,可以使用 len 长度获取。
单向与双向
双向通道
通道默认双向
单向通道
分为 只读信道 和 只写信道。
只读 <-chan 表示这个信道只能从里发出数据
var pipline = make(chan int)
type Receiver = <-chan int
var r Receiver = pipline
只写 chan<- 表示这个信道只能从外面接收数据
waitgroup
要想保证 main goroutine 在所有的 goroutine 都执行完毕后再退出,可以使用信道来标记完成 :
定义一个信道,在任务完成后,往信道中写入true,当在主协程中获取到true,就认为子协程已经执行完毕。
也可以用 sync包 提供的 WaitGroup类型(结构体类型) :
var 实例名 sync.WaitGroup
Add:初始值为0,你传入的值会往计数器上加,这里直接传入你子协程的数量
Done:当某个子协程完成后,可调用此方法,会从计数器上减一,通常可以使用 defer 来调用。
Wait:阻塞当前协程,直到实例里的计数器归零。
锁机制
互斥锁
Mutex可以保护临界区,防止竞争条件,用来保证在任一时刻,只能有一个线程访问该对象。
定义方式:
var 名 *sync.Mutex
名 = new(sync.Mutex)
或
名 := &sync.Mutex{}
加锁 名.Lock()
解锁 名.Unlock()
在Lock和Unlock之间的代码段中的内容goroutine可以随便读取或者修改,这个代码段叫做临界区。
读写锁
RWMutex将程序对资源的访问分为读操作和写操作
读锁占用时,写锁会阻塞
允许多个 只读操作并行执行,但写操作会完全互斥。
var lock *sync.RWMutex
lock = new(sync.RWMutex)
或
lock := &sync.RWMutex{}
读锁:调用 RLock 方法开启锁,调用 RUnlock 释放锁
写锁:调用 Lock 方法开启锁,调用 Unlock 释放锁
最后
以上就是酷炫鸡为你收集整理的go语言自学笔记(三)goroutinechannel锁机制的全部内容,希望文章能够帮你解决go语言自学笔记(三)goroutinechannel锁机制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复