对 GO并发的总结

1. 并发安全和锁两个概念:①临界资源:一次只允许一个进程独占访问(使用的)资源②临界区:进程中访问临界资源的程序段在并发时可能会存在多个goroutine同时操作一个临界资源,这种情况会发生竞态问题(数据竞争),数据竞争会导致最后的结果与期待的不符。这个时候我们可以通过给临界区加锁的方式来控制对共享资源的访问。1.1互斥锁互斥锁可以保证任何时间只允许一个goroutine可以访问共享资源go中使用sync.Mutex来实现互斥锁var lock sync.Mutexlock.Lock
摘要由CSDN通过智能技术生成

1. 并发安全和锁

两个概念:
①临界资源:一次只允许一个进程独占访问(使用的)资源
②临界区:进程中访问临界资源的程序段

在并发时可能会存在多个goroutine同时操作一个临界资源,这种情况会发生竞态问题(数据竞争),数据竞争会导致最后的结果与期待的不符。

这个时候我们可以通过给临界区加锁的方式来控制对共享资源的访问。

1.1互斥锁

互斥锁可以保证任何时间只允许一个goroutine可以访问共享资源
go中使用sync.Mutex来实现互斥锁

var lock sync.Mutex

lock.Lock() // 加锁

//临界资源

 lock.Unlock() // 解锁

多个goroutine同时等待一个锁时,唤醒的策略是随机的
Unlock未加锁的Mutex会Panic

1.2读写互斥锁

在读多写少的情况下,使用读写互斥锁是更好的选择
读写锁分为读锁和写锁
读写锁在Go语言中使用sync.RWMutex

var rwlock sync.RWMutex
rwlock.Lock() // 加写锁
//临界资源
rwlock.Unlock()   // 解写锁

rwlock.RLock()               // 加读锁

rwlock.RUnlock()             // 解读锁

当一个goroutine获取读锁后,其他goroutine也能继续获得读锁,但是不能获取写锁
当一个goroutine获取写锁后,其他goroutine既不能获取读锁,也不能获取写锁

2.Sync

2.1 sync.WaitGroup

在并发时使用time.Sleep是不合适的
通常使用sync.WaitGroup来实现并发同步。

方法 功能
Add (delta) 计数器+delta
Done() 计数器-1
Wait() 阻塞,直到计数器变为0

注意:
如果计数器<0,会panic
Done()等价于Add(-1)
当计数器为0的时候,阻塞在Wait方法的goroutine都会被释放
Add()一定要在Wait()前设置好

2.2 sync.Once

sync.Once 只有一个Do方法,它可以确保某些操作在高并发的场景下只执行一次
例如只加载一次配置文件、只关闭一次通道

对于加载配置文件:
预先初始化一个变量(比如在init函数中完成初始化)会增加程序的启动耗时,而且这个初始化不一定用得上,这个时候就可以用sync.Once
ps.请尽量避免init函数的使用

2.3 sync.Pool

并发池,负责安全地保存一组对象

方法 功能
Get() interface{} 从并发池中取出元素
Put(interface{}) 将一个对象加入并发池

Pool的目的是缓存申请但未使用的item用于之后的重用,以减轻GC的压力
Pool可以安全的被多个线程同时使用
Pool中保存的任何item都可能随时不做通告的释放掉

2.4 sync.Map

GO中内置的map不是并发安全的
在高并发的情况下会:

fatal error: concurrent map writes

sync包中的map是并发安全的,且“开箱即用”,不需要make()初始化就可以直接使用

方法 功能
Store(interface {},interface {}) 添加元素
Load(interface {}) interface {} 检索元素
Delete(interface {}) 删除元素
LoadOrStore(interface {},interface {}) (interface {},bool) 检索或添加之前不 存在的元素
Range 遍历元素

sync.Map的使用场景:
读取map的操作需求远大于写入map的操作
多个goroutine对map的操作不相交时

原子操作(atomic包)

上文中所提到的加锁操作会比较耗时、代价很高
对基本数据类型可以使用原子操作来保证并发安全,原子操作在用户态就可以完成,性能比加锁更好
在这里插入图片描述

channel

channel的功能:
①goroutine之间的通讯
②实现goroutine同步(锁)
无缓冲的channel,在缺省情况下发送和接收会一直阻塞,这种特性可以实现goroutine之间的同步
③实现定时器和计时器

定时器:
在time包中,Timer类型中包含一个只读的channel

type Timer struct {
   
    C <-chan Time
    // 内含隐藏或非导出字段</
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值