首先明确一个观点并行 并发区别:
并行是指程序的运行状态,要有两个线程正在执行才能算是Parallelism;并发指程序的逻辑结构,Concurrency则只要有两个以上线程还在执行过程中即可。简单地说,Parallelism要在多核或者多处理器情况下才能做到,而Concurrency则不需要。golang 利用 go func() 的方式,可以进行多个函数的并行。
我们写C 的时候,假如用到多进程,我们通常都会用信号,管理等来进程进程间的通信, 那么golang是怎么实现这个的呢?? 直接看码说话吧
package main
import (
"fmt"
"time"
)
func main() {
timeout := make(chan bool, 1)
go func() {
fmt.Println("------------ channel 1--------------")
t1 := time.Now().UnixNano()
fmt.Println(t1)
fmt.Println("这个一定会执行")
time.Sleep(3 * time.Second)
// timeout <- true
timeout <- true
}()
fmt.Println("首先逻辑还是响应 main 函数")
go func() {
fmt.Println("------------ channel 2--------------")
t2 := time.Now().UnixNano()
fmt.Println(t2)
fmt.Println("相当于fork一个子进程在进行")
}()
ch := make(chan int)
select {
case <-ch:
case <-timeout:
fmt.Println("------------ 回到main函数 --------------")
fmt.Println("task is timeout!")
}
fmt.Println("main 函数本身的输出")
}
我们执行代码看一看结果
首先逻辑还是响应 main 函数
------------ channel 2--------------
1471577916141068800
相当于fork一个子进程在进行
------------ channel 1--------------
1471577916142068800
这个一定会执行
------------ 回到main函数 --------------
task is timeout!
main 函数本身的输出
分别从 纳秒的时间戳可以看出, 两个 go func() 几乎是同时执行的, 这种是golang并行处理的写法, goroutine是Go语言运行库的功能,不是操作系统提供的功能,goroutine不是用线程实现的。, golang同样提供了一种监视手段去监视每个并行处理逻辑的返回, select就是这种手段
按照目前golang的机制,假如调用select的话,循环监控,假如我们注释掉 timeout <- true 这句, 看看会有什么变化, 我们再执行 go run xx.go 的时候, 会提示 fatal error: all goroutines are asleep - deadlock!, 这是可以理解为我们的 select 监控的多个并行状态都没有回调响应,所以程序一直在等待,造成死锁导致了错误。
其实golang里面也可以用 sync的 waitgroup 进行同步锁,但是这个跟协程并行似乎关系不大,有兴趣的也可以了解下