golang 并发编程基础

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

转载:http://c2pblog.sinaapp.com/archives/450

当今硬件发展迅速,CPU早就变成多核心了,如何处理并发编程以适应多核CPU是每一种现代编程语言做重视的点。golang自出生起就宣扬着并发编程,原生的goroutines和channel 很简洁的支持了复杂的并行操作。
http://blog.csdn.net/gdutliuyun827/article/details/25145535
这篇文章细致分析了Go语言的特色,在此对原作者表示感谢。
下面边上代码边分析实现过程。

func showNum() {
    for i := 0; i < 30; i++ {
        fmt.Println(i)
        atm := time.Duration(rand.Intn(250)) //延迟处理
        time.Sleep(time.Millisecond * atm)
    }
}

这是一个简单的函数,打印出0到29,为了能够看得比较清楚,我做了相关的延迟处理。
如果在主函数中直接去调用这个函数,那么就只能打印一次,这就是非并行化的处理。那么怎么变成并行化呢?很简单,调用的时候在前面加上go就好了。

go showNum()

就像这样。既然是并行,我们就同时调用10次这个函数做一个试验

for i := 0; i < 10; i++ {
        go showNum()
    }

结果你去运行的时候发现什么东西都跑不出来。
不是没有跑出来,太快了,看不到,并且每一次go showNum 的结果都被丢弃了。那么怎么才能看到结果呢?得想一个办法让main停住,那么就写这么一句:

vat in string
fmt.Scanln(&in)

用标准输入给main随便输入一个值。加上这句话以后你去运行就会发现有数字在打印,并且和java 中thread类似,每一次打印都是随机的,无法确定的。这个就是最简单的goroutines了。

简单来说,任何一个函数如果要做并行处理,那么就可以再调用这个函数的时候前面加上关键词go 即可。

要讲的第二个点就是channel,这个是用来实现goroutine之间通信的,就是说两个goroutine之间交换一些信息<当然主要是相关变量>。定义一个channel的方法是向下面这样:

var c1 chan string = make(chan string)
var c2 = make(chan string)
c3 :=make(chan string)

都是可以的。你要注意的是每一个channel必须有一种类型,并且这个类型是不能随便混合使用的。golang中有用很形象的方式来表示信息的传递:这就是<-这个东西,

input <- "lkn"   //input 是一个chan string ,可以接受一个string
data<-input  //input是一个chan string ,用来传出一个string

一般的chan是可以双向传递的,而你如果定义某一个chan只能单向传递的话,可以写成这样:var c2 = make(chan<- string)或者var c2 = make(<-chan string)。前一个表示只能传入,后一个表示只能传出。现在我们用一个简单的打印素数的例子,结合goroutine和channel。

//素数生产者
func prime_generate() chan int {
ch := make(chan int)
go func() {
for i := 2; ; i++ {
ch &lt;- i
}
}()
return ch
}
//素数筛选器
func prime_filter(in chan int, prime int) chan int {
out := make(chan int)
go func() {
for {
if i := &lt;-in; i%prime != 0 {
out &lt;- i
}
}
}()
return out
}
//素数消费者
func prime_sieve() chan int {
out := make(chan int)
go func() {
ch := prime_generate()
for {
prime := &lt;-ch
out &lt;- prime
ch = prime_filter(ch, prime)
}
}()
return out
}

这样就是可以了,主函数里面要这样一直读100次

primes := prime_sieve()
    for i := 0; i &lt; 100; i++ {
        fmt.Println(time.Now(), &lt;-primes)



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

本文来自:CSDN博客

感谢作者:yugongpeng_blog

查看原文:golang 并发编程基础

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

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