Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > Golang 协程配合管道

Golang 协程配合管道的实现示例

作者:富士康质检员张全蛋

本文主要介绍了Golang协程配合管道的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

请完成goroutine和channel协同工作的案例,具体要求:
(1)开启一个writeData协程,向管道mtChan中写入50个整数.
(2)开启一个readData协程,从管道intChan中读取writeData写入的数据。
(3)注意:writeData和readDate操作的是同一个管道
(4)主线程需要等待writeData和readDate协程都完成工作才能退出(如果主线程不做处理,那么其他线程还没干完活就直接跑路了)

管道是引用类型,那么写入读取的都是同一个管道,也就是在不同函数不同栈里面读取的都是同一个管道。两个协程同时的向管道里面写入读取数据,而不是一个写完另外一个协程再去读取。

package main

import (
	"fmt"
)

func writeData(initChan chan int) {
	for i := 0; i <= 50; i++ {
		//放入数据
		initChan <- i
		fmt.Println("write data:", i)
	}
	close(initChan)
}
func readData(initChan chan int, exitChan chan bool) {
	//即使管道close之后并不影响读取,当在管道当中取不到数据才会退出
	for {
		//在从一个管道里面读取会返回两个值,ok是有没有正确读取到
		v, ok := <-initChan
		if !ok {
			break
		}
		fmt.Println("read data:", v)
	}
	//readData任务完成之后
	exitChan <- true
	close(exitChan)
}

func main() {
	//创建两个管道
	initChan := make(chan int, 50)
	exitChan := make(chan bool, 1)

	go writeData(initChan)
	go readData(initChan, exitChan)

	for {
		_, ok := <-exitChan
		fmt.Println("ok=", ok)
		if ok {
			break
		}
	}
}

如果给的容量就是50,那么循环50次就刚好放进去了。如果管道和放进去的数据量不匹配,管道的容量小于放进去的数据,又不取出来,那么它就会阻塞,就会死锁。

这个管道可以容纳的数据量很小,要写的数据量很大,只要一边在写,另外一边在读是无所谓的。

如果写的快,读取的慢。那么在写的时候就会阻塞,编译器会发现虽然阻塞了,但是有另外一个协程在往里面读取数据,这样就不会发生死锁。

func producer(ch chan int) {
	i := 0
	for {
		ch <- i
		i++
	}
}

func main() {
	ch := make(chan int, 2)
	go producer(ch)

	for {
		fmt.Println(<-ch)
		time.Sleep(time.Second * 2)
	}
}

0
1
2
3
4
5
6
7

进程 已完成,退出代码为 -1073741510 (0xC000013A: interrupted by Ctrl+C)

死锁编译器底层会分析,如果发现一个地方在不停的写,但是没有任何一个协程去读取这样就直接死锁,如果有一个协程在慢慢的读取这样不会死锁。和写入读取速度没有关系,但是必须有写入的协程和读取的协程。简而言之就是管道需要不停的流动。

到此这篇关于Golang 协程配合管道的文章就介绍到这了,更多相关Golang 协程配合管道内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文