并发编程2

来源:互联网 发布:网络不给力 编辑:程序博客网 时间:2024/05/16 01:36

多核并行化

根据cpu的数量n,可以将任务拆分成n个goroutine运行

type Vector []float64// 分配给每个CPU的计算任务func (v Vector) DoSome(i, n int, u Vector, c chan int) {for ; i < n; i++ {v[i] += u.Op(v[i])}c <- 1// 发信号告诉任务管理者我已经计算完成了}// 假设总共有16核const NCPU = 16func (v Vector) DoAll(u Vector) {c := make(chan int, NCPU)// 用于接收每个CPU的任务完成信号for i := 0; i < NCPU; i++ {go v.DoSome(i*len(v)/NCPU, (i+1)*len(v)/NCPU, u, c)}// 等待所有CPU的任务完成for i := 0; i < NCPU; i++ {<-c// 获取到一个数据,表示一个CPU计算完成了}// 到这里表示所有计算已经结束}



当前版本的Go编译器还不能很智能地去发现和利用多核的优势。

虽然我们确实创建了多个goroutine,并且从运行状态看这些goroutine也都在并行运行,

但实际上所有这些goroutine都运行在同一个CPU核心上,在一个goroutine得到时间片执行的时候,其他goroutine都会处于等待状态。

从这一点可以看出,虽然goroutine简化了我们写并行代码的过程,但实际上整体运行效率并不真正高于单线程程序。

但是我们可以通过设置环境变量的值来缓解这种情况:

runtime.GOMAXPROCS(runtime.NumCPU())

同步锁

1.锁的种类

sync.Mutex和sync.RWMutex

Mutex简单暴力,如果一个goroutine获取该锁之后,所有其他的goroutine都无法进入。

RWMutex指调用RLock方法时,可以允许多个goroutine进行读操作,但是写操作(Lock()方法)则阻止其他人操作

ps,需要注重事项:1.Lock和UnLock成对出现,否则很容易产生思索

2.defer l.Unlock() 使用defer关键字进行unlock操作

2.全局唯一行操作

sync.Once确保全局只执行一次的目标

使用方法

var a stringvar once sync.Oncefunc setup() {a = "hello, world"}func doprint() {once.Do(setup)print(a)}func twoprint() {go doprint()go doprint()}





0 0
原创粉丝点击