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语言》中的一个例子说明。

clip_image001

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

 

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

 

这里就引进了channel的概念

channel的使用

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

上面的例子就可以改为:

clip_image002

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

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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





本文转自轩脉刃博客园博客,原文链接:http://www.cnblogs.com/yjf512/archive/2012/06/06/2537712.html,如需转载请自行联系原作者

相关文章
|
16天前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
26 7
|
15天前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
16天前
|
程序员 Go
go语言中结构体(Struct)
go语言中结构体(Struct)
92 71
|
15天前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
100 67
|
18天前
|
Go 索引
go语言for遍历数组或切片
go语言for遍历数组或切片
88 62
|
20天前
|
并行计算 安全 Go
Go语言中的并发编程:掌握goroutines和channels####
本文深入探讨了Go语言中并发编程的核心概念——goroutine和channel。不同于传统的线程模型,Go通过轻量级的goroutine和通信机制channel,实现了高效的并发处理。我们将从基础概念开始,逐步深入到实际应用案例,揭示如何在Go语言中优雅地实现并发控制和数据同步。 ####
|
16天前
|
存储 Go
go语言中映射
go语言中映射
32 11
|
18天前
|
Go
go语言for遍历映射(map)
go语言for遍历映射(map)
29 12
|
17天前
|
Go 索引
go语言使用索引遍历
go语言使用索引遍历
26 9
|
21天前
|
安全 Serverless Go
Go语言中的并发编程:深入理解与实践####
本文旨在为读者提供一个关于Go语言并发编程的全面指南。我们将从并发的基本概念讲起,逐步深入到Go语言特有的goroutine和channel机制,探讨它们如何简化多线程编程的复杂性。通过实例演示和代码分析,本文将揭示Go语言在处理并发任务时的优势,以及如何在实际项目中高效利用这些特性来提升性能和响应速度。无论你是Go语言的初学者还是有一定经验的开发者,本文都将为你提供有价值的见解和实用的技巧。 ####