Go语言_并发篇

当被问到为什么用Go语言,一定不得不提的是Go语言的并发程序编写。在C语言中编写非常繁琐复杂的并发程序在Go语言中总是显得如此便捷。

Go中并发程序依靠的是两个:goroutine和channel

理解什么是goroutine?

对于初学者,goroutine直接理解成为线程就可以了。当对一个函数调用go,启动一个goroutine的时候,就相当于起来一个线程,执行这个函数。

实际上,一个goroutine并不相当于一个线程,goroutine的出现正是为了替代原来的线程概念成为最小的调度单位。一旦运行goroutine时,先去当先线程查找,如果线程阻塞了,则被分配到空闲的线程,如果没有空闲的线程,那么就会新建一个线程。注意的是,当goroutine执行完毕后,线程不会回收推出,而是成为了空闲的线程。

关于goroutine的理解,推荐看这个帖子:http://groups.google.com/group/golang-china/browse_thread/thread/0e9d683ca766ec00

goroutine的使用

使用非常简单,在函数前增加一个go

 

f(11)

go f(11) //这个是让f()函数作为goroutine运行

 

但是go有一个缺点,主线程要等待一个goroutine结束再处理怎么办?拿《学习go语言》中的一个例子说明。

这里的第18行为什么要sleep? 这里是为了等上面两个go ready处理完成。

 

好了,这里就出来了一个需求:一个goroutine结束后必须要向主线程传输数据,告诉主线程这个goroutine已经结束了。

 

这里就引进了channel的概念

channel的使用

channel的意思用白话可以这么理解:主线程告诉大家你开goroutine可以,但是我在我的主线程开了一个管道,你做完了你要做的事情之后,往管道里面塞个东西告诉我你已经完成了。

上面的例子就可以改为:

从这个程序得到的几点信息:

1 channel只能使用make来进行创建

基本格式是 c := make(chan int)

int是说明这个管道能传输什么类型的数据

2 往channel中插入数据的操作

c <- 1

是不是很形象

3 从channel中输出数据

<- c

4 为什么需要输出两次(4和5两行?)

因为2和3启动了两个goroutine,每个goroutine都往管道输出一个1,因此主线程要接收两次才能说明两个goroutine都结束了

channel的进一步理解:

http://blog.dccmx.com/2011/05/magic-of-channel-in-go/

http://blog.dccmx.com/2012/03/small-problem-about-goroutine/

 

channel分为两种:一种是有buffer的,一种是没有buffer的,默认是没有buffer的

ci := make(chan int) //无buffer

cj := make(chan int, 0) //无buffer

cs := make(chan int, 100) //有buffer

有缓冲的channel,因此要注意“放”先于“取”

无缓冲的channel,因此要注意“取”先于“放”

http://blog.dccmx.com/2011/05/magic-of-channel-in-go/ 里面的一个例子很好:

 

同样要先输出hello world,使用有缓冲的channel和无缓冲的channel分别是这样的:

有缓冲的channel:

var a string
var c = make(chan int, 10)

func f() {
    a = "hello, world"
    c <- 0
}

func main() {
    go f()
    <-c
    print(a)

}

这里有个缓冲,因此放入数据的操作c<- 0先于取数据操作 <-c

无缓冲的channel:

var a string
var c = make(chan int)

func f() {
    a = "hello, world"
    <-c
}

func main() {
    go f()
    c <- 0
    print(a)

}

由于c是无缓冲的channel,因此必须保证取操作<-c 先于放操作c<- 0

时间: 2024-08-03 21:50:03

Go语言_并发篇的相关文章

Go语言_反射篇

Go语言的基本语法的使用已经在前几篇陆陆续续学完了,下面可能想写一些Go的标准库的使用了. 先是reflect库. reflect库的godoc在http://golang.org/pkg/reflect/ Type和Value 首先,reflect包有两个数据类型我们必须知道,一个是Type,一个是Value. Type就是定义的类型的一个数据类型,Value是值的类型 具体的Type和Value里面包含的方法就要看文档了: http://golang.org/pkg/reflect/   这

Go语言_接口篇

在Go中,接口interface其实和其他语言的接口意思也没什么区别.interface理解其为一种类型的规范或者约定.一种类型是不是"实现"了一个接口呢?就看这种类型是不是实现了接口中定义的所有方法. 1 接口的定义和使用. 比如 1 2 3 4 5 type I interface{     Get() int     Put(int)   } 这段话就定义了一个接口,它包含两个函数Get和Put   好了,我的一个接口实现了这个接口: 1 2 3 4 5 6 7 8 type S

java语言程序设计基础篇4.1

问题描述 java语言程序设计基础篇4.1 java语言程序设计基础篇4.1java语言程序设计基础篇4.1java语言程序设计基础篇4.1 解决方案 除非你有先天性智力缺陷,否则这种问题都不会的基本都是自己根本不学的.既然你都不想学,你还提什么问题,早点回家算了,可怜你父母的学费. 解决方案二: <Java语言程序设计(基础篇)>读书笔记(一)<Java语言程序设计(基础篇)>读书笔记(四)java语言程序设计-基础篇-4.21习题

100分求java语言程序设计进阶篇pdf

问题描述 求java语言程序设计进阶篇pdf 解决方案 解决方案二:同求啊!!!解决方案三:这个网上是没有的,我也在网上找过,我建议你去网上找java核心技术<上下卷>pdf这本书写的也是不错的,,这个网上有电子书的,,这两本书配合着java编程思想,相当的不错的解决方案四:真正的进阶是需要项目练习的,纸上得来终觉浅解决方案五:引用2楼xinzailiulei的回复: 这个网上是没有的,我也在网上找过,我建议你去网上找java核心技术<上下卷>pdf这本书写的也是不错的,,这个网上

Go语言_基础学习篇

GO文件目录结构 该图是go-windows的目录结构   如图,go的程序应该是在gopath文件夹下的,分为bin, pkg, 和src三个子文件夹 src文件夹:每个次级文件夹(如demo)就是代表一个go项目,里面存放源程序 bin文件夹:go的每个项目生成的二进制可执行程序.windows下会生成.exe文件,linux下会生成可执行文件.Go的最大特色之一就是可移植性,就是说,当生成一个demo.exe之后,将这个exe文件放在任意一台windows系统上(即使没有安装go安装包),

Go语言_函数学习篇

这里要说一下是Go函数和一些其他语言不一样的地方 1 函数格式不同 1 2 3 4 5 6 func GetMsg(i int) (r string) {     fmt.Println(i)     r = "hi"     return r   } func说明这个是个函数 GetMsg是函数名 (i int) 函数接收一个int参数 (r string) 函数返回一个string类型返回值 2 函数可以返回多个返回值 这点和c,php都不一样,和lua是一样的 1 2 3 4 5

求 《java语言程序设计_进阶篇》课后完整答案

问题描述 如题,可以的话发到54438561@qq.com.或者给个淘宝网站什么的,我去买也行啊.谢谢啊. 解决方案 解决方案二:不知道,从未看过这类东西

【Go语言】【16】GO语言的并发

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://qingkechina.blog.51cto.com/5552198/1678483        在写该文之前一直犹豫,是把Go的并发写的面面俱到显得高大尚一些,还是简洁易懂一些?今天看到一个新员工在学习Java,突然间想起第一次接触Java的并发时,被作者搞了一个云里雾里,直到现在还有阴影,所以决定本文从简.哈哈,说笑了,言归正传.        Go的并发真的很简单,所以本

人大复印资料处理程序_查询篇_php基础

<? //本程序为一个搜索,目前设计服务于文章库. //编者:孔秀祥.日期:2001/4/10 if(!$UploadAction): require "config.php3"; if(!isset($table)){ //$table="artical"; } /* $link_id=@MYSQL_CONNECT($hostname,$dbusername,$dbpassword) OR DIE("不能连接数据库!"); @mysql_