go 并发入门案例之goroutine +channel (学会就初中毕业了)

并发的特点:多个任务作用在一个cpu,从微观的角度看一个时间点其实只有一个任务在执行

并行的特点:多个任务作用在多个cpu,从微观的角度看,在一个时间点上多个任务同时执行,这样看来并行的速度更快

Go的协程:main.exe可以看醉哦是线程,也可以理解成进程,go可以轻松运行上十万个协程goroutine,(轻量级的线程),java这种语言千机的线程就可以耗光CPU了

协程资源竞争问题使用sync lock的是低水平的程序员,高水平的使用channel的

go build -race xxx.go可以看不到详细的输出,有没有资源竞争

clannel 管道,其实就是一个数据类型,可以理解成队列FIFO先进先出,first in first out

channel是线程安全的(因为它其实是一个队列)多个协程同时操作一个线程是不会发生资源竞争问题的,所以它是线程安全的

 

go 并发入门案例(幼儿园考试篇)goroutine +channel

package main

import (
	"fmt"
)

func writeData(wChan chan int,num int){

	for i:=0;i<num;i++{
		wChan<-i//把i写入管道
		if num%1000==0{
			fmt.Println("写入到管道的值:",i)
		}
	}

	close(wChan)//写完关闭管道,写完必须关闭哦,不关闭下面遍历会出错的
}
func readData(myWriteintChan chan int,exit chan bool){

	for v:=range myWriteintChan{
		if v%1000==0{
			fmt.Println("读取到管道的值:",v)
		}
	}

	exit<-true//读取完管道,标记可以关闭管道
}
func main(){

	myNum := 99999
	myWriteintChan := make(chan int,myNum)

    //这里也可以用变量,不一定要管道,用变量的话readData返回个读取完毕的值,
    //for阻塞的地方就判断返回值
	existChan := make(chan bool,1)

	go writeData(myWriteintChan,myNum)
	go readData(myWriteintChan,existChan)

	existFlag := <-existChan

	//for阻塞起来,直到读取完毕就退出程序
	for{
		if existFlag==true{
			break
		}
	}
}

go 并发入门案例二(小学毕业篇) goroutine +channel

1.开启一个协程,把1-1000的数据写入到管道

2.开启十个协程,从管道中读取数据,把读取到的数据写入到结果集管道

3.遍历结果集管道,计算1-1000相加的结果,输出结果

注意事项:1.使用完毕的管道记得关闭,在管道遍历之前需要关闭管道

 结果:1-1000相加的结果是:500500

package main

import (
	"fmt"
)

func inChan(inchannel chan int,num int){
	for i:=1;i<=num;i++{
		inchannel <- i//把i写入管道中
	}
	close(inchannel)//写入完毕,关闭管道
}
//读取管道的内容,把读取到的内容放入到
func readChan(readChannel chan int,resChan chan int,exitChan chan bool){
	//每个协程进入这都阻塞读取管道的内容,直到管道没数据了,就退出
	for{
		getChannelValue,ok := <-readChannel //读取管道的内容
		if !ok{//判断管道的读取内容是否为真
			fmt.Println("readChan退出读取:",getChannelValue,ok)
			//这里不能关闭管道哦,因为你取不到结果,可能别的协程能取到结果
			exitChan <- true
			break
		}
		resChan<-getChannelValue//数据读取成功,把从管道读取的数据放到结果管道
	}
}

func main(){
	//启动一个协程把1-1000的数据放到管道中
	//启动10个协程消费管道里面的结果集,把获取到的结果放到新的管道里面(注意需等待所有协程执行完毕)

	//创建一条管道并make定义管道数据类型并分配空间
	yourNum  := 1000
	groutine := 10
	numChan  := make(chan int,yourNum)//1-1000写入到这个管道
	resChan  := make(chan int,yourNum)//读取到的数据放到这个管道
	exitChan := make(chan bool,10)	  //关闭管道标记
	resultNum:=0 //计算结果

	//启动一个协程,往管道写入数据
	go inChan(numChan,yourNum)

	//启动10个进程取读取管道的内容
	for i:=1;i<=groutine;i++{
		go readChan(numChan,resChan,exitChan)
	}

	//把结果集的管道阻塞起来,直到结果集全部拿到,然后关闭管道
	exitFlag,ok := <-exitChan
	fmt.Println("exitChan:",exitFlag,ok)
	if exitFlag==true {
		close(resChan)//关闭结果集管道,下面才能遍历管道
	}

	//这个exitChan不能直接关闭,因为有十个协程同时在,取最后一个数据的时候,其他9个可能没有退出的
	//直接关闭了的话会导致后面9个写入管道时候会报错
	defer close(exitChan)

	for chanValue:=range resChan{
		resultNum = resultNum+chanValue
		fmt.Print(" ",chanValue)
	}

	fmt.Printf("\n 1-%v相加的结果是:%v",yourNum,resultNum)
	//1-1000相加的结果是:500500
}

 

开发中用到waitGroup需要注意死锁问题:go wait group dead 死锁问题

并发时候保证公共数据安全问题加锁问题注意事项https://blog.csdn.net/qq_27517377/article/details/114824259

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值