每一个并非的执行单元叫作一个goroutine.设想这里的一个程序有两个函数,一个函数做计算,另一个输出结果,假设两个函数没有相互之间的调用关系。一个线性的程序会先调用其中的一个函数,然后再调用另一个。如果程序中包含多个goroutine,对两个函数的调用规则可能发生再同一时刻。马上就会看到这样的一个程序。

当一个程序启动时,其主函数即再一个单独的goroutine中运行,我们叫它main goroutine。新的goroutine会用go语句来创建。在语法上,go语句是一个普通的函数或方法调用前加上关键字go。go语句会使其语句中的函数在一个新创建的goroutine中运行。而go语句本身会迅速地完成。
f() // call f(); wait for it to return
go f() // create a new goroutine that calls f();dont wait // 示例
main goroutine将计算斐波那契数列的第45个元素值、由于计算函数使用低效的递归,所以会运行相当长时间,在此期间我们想让用户看到一个可见的标识来表明程序依然在正常运行,所以来做一个动画的小图标:
func main(){
go spinner(100 * time.Millisecond) // 开启协程
const n = 45
fibN := fib(n) // slow
fmt.Printf("\rFibonacci(%d) = %d\n", n, fibN)
} func spinner(delay time.Duration){
for {
for _, r := range `-\|/`{
fmt.Printf("\r%c", r)
time.Sleep(delay)
}
}
} func fib(x int) int{
if x<2{
return x
}
return fib(x-1) + fib(x-2)
} 动画显示了几秒之后,fib(45)的调用成功的返回,并且打印结果:
Fibonacci(45) = 1134903170
然后主函数返回。主函数返回时,所有的goroutine都会被直接打断,程序退出。除了从主函数退出或者直接终止程序之外,没有其它的编程方法能够让一个goroutine来打断另一个的执行,但是之后可以看到一种方式来实现这个目的,通过goroutine之间的通信来让一个goroutine请求其它的goroutine,并让被请求的goroutine自行结束执行。 // 示例:并非的Clock服务
package main import (
"io"
"log"
"net"
"time"
) func main(){
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil{
log.Fatal(err)
} for {
conn, err := listener.Accept()
if err != nil{
log.Print(err)
continue
}
handleConn(conn)
}
} func handleConn(c net.Conn){
defer c.Close()
for {
_, err := io.WriteString(c, time.Now().Format("15:04:05\n"))
if err != nil{
return
}
time.Sleep(1 * time.Second)
}
}
Listen函数创建了一个net.Listener的对象,这个对象会监听一个网络端口上到来的连接,在这个例子里我们用的是TCP的localhost:8000端口。listener对象的Accept方法会直接阻塞,直到一个新的连接被创建,然后会返回一个net.Conn对象来表示这个连接。 handleConn函数会处理一个完整的客户端连接。在一个for死循环中,用time.Now()获取当前时刻,然后写到客户端。由于net.Conn实现了io.Writer接口,我们可以直接向其写入内容,这个死循环会一直执行,直到写入失败,最可能的原因是客户端主动断开连接。这种情况下handleConn函数会用defer调用关闭服务器的连接,然后返回到主函数,继续等待下一个连接请求。 time.Time.Format方法提供了一种格式化日期和时间信息的方式。它的参数是一个格式化模板,标识如何来格式化时间,而这个格式化模板限定为Mon Jan 2 03:04:05PM 2006 UTC-0700。有8个部分(周几 月份 一个月的第几天..)
可以以任意的形式来组合前面这个模板;出现在模板中的部分会作为参考来对时间格式进行输出。在上面的例子中我们只用到了小时,分钟和秒。 //客户端连接服务端
package main import (
"io"
"log"
"net"
"os"
)
func main(){
conn, err := net.Dial("tcp", "localhost:8000")
if err != nil{
log.Fatal(err)
}
defer conn.Close()
mustCopy(os.Stdout, conn)
}
func mustCopy(dst io.Writer, src io.Reader){
if _, err := io.Copy(dst, src); err!=nil{
log.Fatal(err)
}
} 上面的服务器程序同一时间只能处理一个客户端连接,这边我们将其改成支持并发。在handleConn函数调用的地方增加go关键字,让每一次handleConn的调用都进入一个独立的goroutine
for{
conn, err := listener.Accept()
if err != nil{
log.Print(err)
contine
}
go handleConn(conn)
}

goroutine并发的更多相关文章

  1. Goroutine并发调度模型深度解析之手撸一个协程池

    golanggoroutine协程池Groutine Pool高并发 并发(并行),一直以来都是一个编程语言里的核心主题之一,也是被开发者关注最多的话题:Go语言作为一个出道以来就自带 『高并发』光环 ...

  2. 说说Golang goroutine并发那些事儿

    摘要:今天我们一起盘点一下Golang并发那些事儿. Golang.Golang.Golang 真的够浪,今天我们一起盘点一下Golang并发那些事儿,准确来说是goroutine,关于多线程并发,咱 ...

  3. GO语言的进阶之路-goroutine(并发)

    GO语言的进阶之路-goroutine(并发) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 有人把Go比作21世纪的C 语言,第一是因为 Go语言设计简单,第二,21世纪最重要的 ...

  4. goroutine 分析 协程的调度和执行顺序 并发写

    package main import ( "fmt" "runtime" "sync" ) const N = 26 func main( ...

  5. goroutine 分析 协程的调度和执行顺序 并发写 run in the same address space 内存地址 闭包 存在两种并发 确定性 非确定性的 Go 的协程和通道理所当然的支持确定性的并发方式(

    package main import ( "fmt" "runtime" "sync" ) const N = 26 func main( ...

  6. Go语言学习之8 goroutine详解、定时器与单元测试

    主要内容: 1.Goroutine2. Chanel3. 单元测试 1. Goroutine Go 协程(Goroutine)(轻量级的线程,开线程没有数量限制).   (1)进程和线程 A. 进程是 ...

  7. golang中map并发读写问题及解决方法

    一.map并发读写问题 如果map由多协程同时读和写就会出现 fatal error:concurrent map read and map write的错误 如下代码很容易就出现map并发读写问题 ...

  8. Go语言 7 并发编程

    文章由作者马志国在博客园的原创,若转载请于明显处标记出处:http://www.cnblogs.com/mazg/ Go学习群:415660935 今天我们学习Go语言编程的第七章,并发编程.语言级别 ...

  9. Go语言之并发编程(四)

    同步 Go 程序可以使用通道进行多个 goroutine 间的数据交换,但这仅仅是数据同步中的一种方法.通道内部的实现依然使用了各种锁,因此优雅代码的代价是性能.在某些轻量级的场合,原子访问(atom ...

  10. [GO语言的并发之道] Goroutine调度原理&Channel详解

    并发(并行),一直以来都是一个编程语言里的核心主题之一,也是被开发者关注最多的话题:Go语言作为一个出道以来就自带 『高并发』光环的富二代编程语言,它的并发(并行)编程肯定是值得开发者去探究的,而Go ...

随机推荐

  1. 周末拾遗 xsos 的学习与使用

    周末拾遗 xsos 的学习与使用 摘要 周末陪儿子上跆拳道课. 自己一个人傻乎乎的开着笔记本想着学习点东西. 上午看到了一个sosreport的工具. 本来想学习一下. 发现xsos 应该是更好的一个 ...

  2. 部分信创CPU算力与IntelCPU的简单比较

    部分信创CPU算力与IntelCPU的简单比较 摘要 最近一直想查看一下国产和非国产的CPU的性能比较 从最开始学习研究 sysbench 到周五晚上开始学习 stress-ng 今天查看github ...

  3. 除了Adobe之外,还有什么方法可以将Excel转为PDF?

    前言 Java是一种广泛使用的编程语言,它在企业级应用开发中发挥着重要作用.而在实际的开发过程中,我们常常需要处理各种数据格式转换的需求.今天小编为大家介绍下如何使用葡萄城公司的的Java API 组 ...

  4. add_argument()方法基本参数使用

    selenium做web自动化时我们想要通过get打开一个页面之前就设置好一些基本参数,需要 通过add_argument()方法来设置,下面以一个简单的不展示窗口为例. option = webdr ...

  5. js中toString方法的三个作用

    toString方法的三个作用: 1.返回一个[表示对象]的[字符串] 2.检测对象的类型 Object.prototype.toString.call(arr)==="[object Ar ...

  6. 从零开始配置 vim(7)——自动命令

    这篇我们来谈论vim一个相当重要的东西--自动命令. 从编程的角度来看,自动命令有点类似于事件响应,或者回调函数之类.当外部发生某些事件的时候,自动执行事先定义好的一组命令. 定义一个自动命令的格式如 ...

  7. 从零开始配置 vim(4)——键盘映射的一些技巧

    通过前面的学习,我们已经知道了如何进行键盘映射,并且也知道了在任何场合应该使用非递归版本的映射.这篇再介绍一些使用关于快捷键映射的内容作为收尾 快速编辑 vimrc 文件 通过前面掌握的知识,相信各位 ...

  8. 4.6 Windows驱动开发:内核遍历进程VAD结构体

    在上一篇文章<内核中实现Dump进程转储>中我们实现了ARK工具的转存功能,本篇文章继续以内存为出发点介绍VAD结构,该结构的全程是Virtual Address Descriptor即虚 ...

  9. PBKDF2算法:保护密码安全的重要工具

    摘要:在当今的数字世界中,密码安全是至关重要的.为了保护用户密码免受未经授权的访问和破解,Password-Based Key Derivation Function 2 (PBKDF2)算法成为了一 ...

  10. CF911G Mass Change Queries 题解

    题目链接:CF 或者 洛谷 前置知识点:平衡树合并: CF文章 与维基百科 看上去这题有很多人用线段树分裂与合并去做,其实这种需要分裂和合并的,我们用文艺平衡树去维护区间信息是最容易写的. 考虑本题的 ...