天天看点

Go-Goroutine-Channel-基础理解

Go 提供了一个关键字go 

用于执行并发操作的关键字 所以说Go从语言层面上就支持了并发 

其中go 关键字启动的是一个协程这里并非线程 协程是轻量级的 有可能10几个协程下对应了5,6个线程go语言自动帮我们管理

其实和java中的线程池 我个人觉得还是很类似的 

只不过java中的线程池有多种实现方式 如schedule single fix buffer 各有不同的使用场景

目前我还是不太清楚这种替我们管理线程的方式是好或不好  毕竟不是大牛 先用着再说吧 

Goroutine - 协程

通过go关键字就可以直接启动一个协程

Channel - 协程间通信的通道

管道应该很好理解 就和Java里面的IO流管道式一个道理一边进一边出

在Go中 如果调用了内置函数close关闭之后 便无法再向管道中写入数据但是仍然可以继续读取数据

做汉堡包的人--简称厨师

比如麦当劳里面买汉堡包 厨师后台做好了一个汉堡包 如果是在一个比较大的麦当劳店里会有一台机器,厨师把汉堡放到机器中然后继续做自己的事,机器负责把这个做好的汉堡运送到前面的那个保温的透明箱子里 ,也就是我们每回点餐时都能看到的那个 里面放了很多汉堡 鸡腿 鸡块啥的 ,如果有人点了汉堡 前台收银员就会从这里面拿一个汉堡出来给顾客 然后继续做自己的事 

这整个过程如果按照Go里面的说法就是完成了协程之间的通信 厨师就是协程1  前台收银员就是协程2 而中间所有的部分都是Channel

通过代码示例更容易懂

channel := make(chan int) 这样就声明了一个阻塞式的无缓冲的通道 

chan 是关键字 代表我要创建一个通道 

int则代表该通道所能接受的数据类型为int

那么如果有两个A,B两个协程 在放入和取出数据时都只能用int类型的数据进行通信

如 取数据 <- channel 放数据 channel <- 1 

协程之间可以通过在通道中放入-取出数据的方式进行通信

用代码展示下无阻赛的Channel是如何在协程之间实现通信

示例  并发计算

package main

import (
	"fmt"
)

func sum(arr []int,c chan int){
	num := 0
	for _,v := range arr {
		num += v
	}
	//放入数据到通道中 --- 如此一来 主协程中一发现通道中有数据就会立刻取出数据了
	c <- num
}

func main() {
	//创建一个通信通道
	c := make(chan int)
	slice := []int {1,2,3,4,5,6,7,8,9,10}
	//启动协程 1
	go sum(slice[0:len(slice)/2],c)
	//启动协程 2
	go sum(slice[len(slice)/2:],c)
	//阻塞式 接受来自 协程1,2的返回结果
	num1, num2 := <- c, <- c
	fmt.Println(num1, num2, num1+num2)
}