![](https://img.haomeiwen.com/i2051731/8b2ea83d66afba4e.jpg)
本文是在上一篇文章的基础上Golang之并发编程一的基础上的续篇,如果有兴趣的话,大家可以先看看上一篇的内容,也希望能给出建议,谢谢。
好了,那接下来继续说Golang的并发编程吧。
多核并行化
在说到Golang的并行化时,先看看并行和并发分别是什么吧。
并发:是在单核cpu的基础上,线程通过时间片或者争夺和让出控制权来实现任务的切换,从而实现多个任务的执行。表面上看就好像多个任务在“同时”进行,而其实在某个时间点上,有且仅有一个任务在执行而已。
并行:是指多核的CPU能让同一个进程内的线程,实现真正意义上的同时运行,在理想情况下是不需要排队的(实际是线程数量往往多余cpu核数)。
在目前的Go编译器中,还不能够发挥多核cpu的优势,虽然通过参加goroutine可以实现多并发,简化并行代码的编写,但这些goroutine都运行在同一个CPU核心上,在一个goroutine得到时间片执行的时候,其他goroutine都会处于等待状态,所以有时候的实际效率可能并没有单线程的高。
所以在目前的Golang版本中,我们可以通过设置环境变量来控制使用多少个CPU核心。
runtime.GOMAXPROCS(16)
通过设置环境变量GOMAXPROCS的cpu核数,我们可以指定使用多少个cpu核心,另外,我们可以通过NumCPU()的方法,来获取当前计算机的cpu核数。
runtime.NumCPU()
出让时间片
runtime.Gosched()
当调用这个方法后,该goroutine的会让出自己的时间片让其他goroutine执行。
需要注意的还有一点:当一个goroutine发生阻塞,Go会自动地把与该goroutine处于同一系统线程的其他goroutines转移到另一个系统线程上去,以使这些goroutines不阻塞
同步
虽然使用了channel来作为通信手段,但还是可能避免不了goroutine间的共享数据,所以在golang中,还是提供了资源锁的方案
同步锁
Golang中提供了两种锁类型:sync.Mutex 、sync.RWMutex
Mutex:类似Java中的Lock,一个goroutine获取锁后其他goroutine只能够等待,无论读写操作。
RWMutex:类型Java中的读写锁,读锁占用时,锁写操作,写锁占用时,读写都锁住。
全局唯一性操作
对于全局中只需要运行一次的代码,如初始化操作,golang提供了一个Once类型来保证唯一性操作
var once sync.Once
once.Do(方法名)
调用once.Do时,其他goroutine会被阻塞,知道全局唯一的once.Do()调用结束后才继续
示例:
var a string
var once sync.Once
func setup() {
a = "hello world"
}
func doprint() {
once.Do(setup)
print(a)
}
额外阅读:golang线程同步WaitGroup
网友评论