这篇文章给大家介绍Go 语言中协程通信实现的共享内存是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
go
memory.go
package main
import (
"fmt"
"runtime"
"sync"
)
var counter int = 0
func add(a, b int, lock *sync.Mutex) {
c := a + b
lock.Lock()
counter++
fmt.Printf("%d: %d + %d = %d\n", counter, a, b, c)
lock.Unlock()
}
func main() {
start := time.Now()
lock := &sync.Mutex{}
for i := 0; i < 10; i++ {
go add(1, i, lock)
}
for {
lock.Lock()
c := counter
lock.Unlock()
runtime.Gosched()
if c >= 10 {
break
}
}
end := time.Now()
consume := end.Sub(start).Seconds()
fmt.Println("程序执行耗时(s):", consume)
}
countercounter
countercountersync.MutexLock()sync.MutexUnlock()sync.Mutexlock.Lock()lock.Unlock()counter
最后,我们还统计了整个程序执行时间。
当我们执行这段代码时,打印结果如下:
可以看到,实际执行时间远远小于1秒,这样一来,程序的整体执行效率相比于上篇教程的实现快了将近1万倍。
不过,代码也因此变得更复杂,更难以维护,这还只是个简单的加法运算实现,就要写这么多代码,要引入共享变量,还要引入互斥锁来保证操作的原子性,对于更加复杂的业务代码,如果到处都要加锁、解锁,显然对开发者和维护者来说都是噩梦,Go 语言既然以并发编程作为语言的核心优势,当然不至于将这样的问题用这么繁琐的方式来解决。
前面我们说,除了共享内存之外,还可以通过消息传递来实现协程通信,Go 语言本身的编程哲学也是「Don’t communicate by sharing memory, share memory by communicating」,所以实际上,我们在 Go 语言并发编程实践中,使用的都是基于消息传递的方式实现协程之间的通信。
在消息传递机制中,每个协程是独立的个体,并且都有自己的变量,与共享内存不同的是,在不同协程间这些变量不共享,每个协程的输入和输出都只有一种方式,那就是消息,这有点类似于进程:每个进程都是独立的,不会被其他进程打扰,不同进程间靠消息来通信,它们不会共享内存。
关于Go 语言中协程通信实现的共享内存是怎样的就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。