Golang并发以及通道的使用

yjp19871013 · · 717 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yjp19871013/article/details/81805919

Golang最擅长的就是并发编程,使用Golang可以很方便的进行并发编程。先看一段普通的代码

package main

import (
	"fmt"
	"time"
)

func Foo(i int) {
	fmt.Printf("%d will sleep\n", i)
	time.Sleep(5 * time.Second)
	fmt.Printf("%d wake up\n", i)
}

func main() {
	for i := 0; i < 5; i++ {
		Foo(i)
	}
}

输出为

0 will sleep
0 wake up
1 will sleep
1 wake up
2 will sleep
2 wake up
3 will sleep
3 wake up
4 will sleep
4 wake up

大概要执行25秒的时间,因为我们的foo中休眠5s,5次循环,去掉其他时间至少需要25秒时间执行完成。现在,我们希望并发调用Foo函数,很简单,使用go关键字创建协程(协程比线程的执行更加轻量级)

package main

import (
	"fmt"
	"time"
)

func Foo(i int) {
	fmt.Printf("%d will sleep\n", i)
	time.Sleep(5 * time.Second)
	fmt.Printf("%d wake up\n", i)
}

func main() {
	for i := 0; i < 5; i++ {
		go Foo(i)
	}

	time.Sleep(10 * time.Second)
}

在调用Foo前使用了go,这样就会并发执行,最后添加休眠10秒,是防止主进程结束,协程也被销毁。下面的例子使用通道我们可以看到更优雅的解决方法。

package main

import (
	"fmt"
	"time"
)

func Foo(i int, ch chan int) {
	fmt.Printf("%d will sleep\n", i)
	time.Sleep(5 * time.Second)
	fmt.Printf("%d wake up\n", i)
	ch <- 1
}

func main() {
	ch := make(chan int)

	for i := 0; i < 5; i++ {
		go Foo(i, ch)
	}

	count := 0
	for count < 5 {
		count += <-ch
	}
}

通道属于复合类型,我们使用make函数创建通道,通道类型是int,也就是我们可以使用该通道传递int类型的值。我们在主函数中向Foo函数传递通道作为参数,当Foo函数执行结束后,通过通道发送数字1(ch <- 1),在主函数中我们进行计数,从通道中读取值(<- ch),当通道中没有值的时候,我们将阻塞等待。当五个协程都执行结束后退出循环。使用通道,我们还可以实现生产者和消费者模式。

package main

import (
	"fmt"
	"math/rand"
)

func Consumer(ch <-chan int, result chan<- int) {
	sum := 0
	for i := 0; i < 5; i++ {
		sum += <-ch
	}

	result <- sum
}

func Producer(ch chan<- int) {
	var num int
	for i := 0; i < 5; i++ {
		rand.Seed(20)
		num = rand.Intn(100)
		ch <- num
	}
}

func main() {
	ch := make(chan int)
	result := make(chan int)
	go Producer(ch)
	go Consumer(ch, result)

	fmt.Printf("result: %d\n", <-result)
}

我们在生产者和消费者之间使用ch通道传递数据,使用reslut通道给主函数返回结果。注意观察Consumer函数和Producer函数的参数列表,这里通道参数的传递略有不同,指明了通道的方向,chan<-代表我们可以向通道写数据,但是不能使用通道读数据,<-chan正好相反,只能从通道中读取数据而不可以写入数据。

可以看到,go语言实现并发非常简单,借用通道,又可以在不同的协程之间方便的传输数据。

 


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:yjp19871013

查看原文:Golang并发以及通道的使用

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

717 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传