不知道你有没有注意到,这段代码如果我跑在两个goroutines里面的话:

  

package main

import (
"fmt"
) func loop(done chan bool) {
for i := 0; i < 10; i++ {
fmt.Print(i)
}
done <- true
} func main() {
done := make(chan bool)
go loop(done)
go loop(done) <-done
<-done }

他的输出结果: 01234567890123456789

go不是会新起一个goroutine来运行loop函数吗。以前我们用线程去做类似任务的时候,系统的线程会抢占式地输出, 表现出来的是乱序地输出。而goroutine为什么是这样输出的呢?

关于并行和并发,下面这张图说明:

  • 两个队列,一个Coffee机器,那是并发
  • 两个队列,两个Coffee机器,那是并行

默认地, Go所有的goroutines只能在一个线程里跑 。

如果当前goroutine不发生阻塞,它是不会让出CPU给其他goroutine的, 所以上面的例子的输出会是一个一个goroutine进行的

真正的并行

为了达到真正的并行,runtime.GOMAXPROCS(2)试试看

package main

import (
"fmt"
"runtime"
) func loop(done chan bool) {
for i := 0; i < 100; i++ {
fmt.Printf("%d ", i)
}
done <- true
} func main() {
runtime.GOMAXPROCS(2)
done := make(chan bool)
go loop(done)
go loop(done) <-done
<-done }

这下会看到两个goroutine会抢占式地输出数据了。我们还可以这样显式地让出CPU时间:

package main

import (
"fmt"
"runtime"
) func loop(done chan bool) {
for i := 0; i < 100; i++ {
fmt.Printf("%d ", i)
runtime.Gosched() //// 显式地让出CPU时间给其他goroutine
}
done <- true
} func main() {
// runtime.GOMAXPROCS(2)
done := make(chan bool)
go loop(done)
go loop(done) <-done
<-done }

总结

我们从例子中可以看到,默认的, 所有goroutine会在一个原生线程里跑

在同一个原生线程里,如果当前goroutine不发生阻塞,它是不会让出CPU时间给其他同线程的goroutines的,这是Go运行时对goroutine的调度,我们也可以使用runtime包来手工调度。

当一个goroutine发生阻塞,Go会自动地把与该goroutine处于同一系统线程的其他goroutines转移到另一个系统线程上去,以使这些goroutines不阻塞

Go语言的并发和并行的更多相关文章

  1. Go语言并发与并行学习笔记(二)

    转:http://blog.csdn.net/kjfcpua/article/details/18265461 Go语言的并发和并行 不知道你有没有注意到一个现象,还是这段代码,如果我跑在两个goro ...

  2. go并发和并行

    Go语言的并发和并行 不知道你有没有注意到一个现象,还是这段代码,如果我跑在两个goroutines里面的话: var quit chan int = make(chan int) func loop ...

  3. Go语言并发与并行学习笔记(三)

    转:http://blog.csdn.net/kjfcpua/article/details/18265475 Go语言并发的设计模式和应用场景 以下设计模式和应用场景来自Google IO上的关于G ...

  4. geotrellis使用(六)Scala并发(并行)编程

    本文主要讲解Scala的并发(并行)编程,那么为什么题目概称geotrellis使用(六)呢,主要因为本系列讲解如何使用Geotrellis,具体前几篇博文已经介绍过了.我觉得干任何一件事情基础很重要 ...

  5. Python 多线程教程:并发与并行

    转载于: https://my.oschina.net/leejun2005/blog/398826 在批评Python的讨论中,常常说起Python多线程是多么的难用.还有人对 global int ...

  6. Python并发与并行的新手指南

    点这里 在批评Python的讨论中,常常说起Python多线程是多么的难用.还有人对 global interpreter lock(也被亲切的称为“GIL”)指指点点,说它阻碍了Python的多线程 ...

  7. 《Go in action》读后记录:Go的并发与并行

    本文的主要内容是: 了解goroutine,使用它来运行程序 了解Go是如何检测并修正竞争状态的(解决资源互斥访问的方式) 了解并使用通道chan来同步goroutine 一.使用goroutine来 ...

  8. [Go] 并发和并行的区别

    并发和并行的区别:1.并行是让不同的代码片段同时在不同的物理机器上运行,并行的关键是在不同的物理机器上同时运行 2.并发是同时管理很多事情,比如在一个物理机器上进行不停的调度,有些事情可能只做了一半就 ...

  9. Go语言的并发

    一.Go语言中Goroutine的基本原理 Go语言里的并发指的是能让某个函数独立于其他函数运行的能力. Go语言的goroutine是一个独立的工作单元, Go 语言的并发同步模型来自一个叫作通信顺 ...

随机推荐

  1. wpa_supplicant与kernel交互

    wpa_supplicant与kernel交互的操作,一般需要先明确驱动接口,以及用户态和kernel态的接口函数,以此来进行调用操作.这里分为4个步骤讨论. 1.首先需要明确指定的驱动接口.因为有较 ...

  2. Alpha发布文案+美工

    文案: Alpha发布文稿 我们是Hello World!团队,下面由我来简要介绍一下我们组的作品,我们组做的是一个飞机射击类游戏,名字叫做空天猎.这个游戏是基于JAVA平台创建的,那么接下来让我给大 ...

  3. python异步初步窥探

    1.异步之难:因为其执行吮吸不可预料,当下正要发生什么事件不可预料.        程序下一步行为往往依赖上一步值执行结果,如何知晓上次异步调用已完成并获取结果,        回调成了必然选择,那又 ...

  4. JavaScript初探系列之面向对象

    面向对象的语言有一个标志,即拥有类的概念,抽象实例对象的公共属性与方法,基于类可以创建任意多个实例对象,一般具有封装.继承.多态的特性!但JS中对象与纯面向对象语言中的对象是不同的,ECMA标准定义J ...

  5. LintCode-376.二叉树的路径和

    二叉树的路径和 给定一个二叉树,找出所有路径中各节点相加总和等于给定 目标值 的路径. 一个有效的路径,指的是从根节点到叶节点的路径. 样例 给定一个二叉树,和 目标值 = 5: 返回: [      ...

  6. ubuntu下修改MySQL的配置文件my.cnf

    先sudo su转换成root,再用cd转到/etc/MySQL目录下,用chmod修改权限(chmod 755 my.cnf),但这样还不能修改,再用vi命令(vi my.cnf),通过上下方向键将 ...

  7. 【ASP.NET Core】- 搭建MVC框架

    1.使用最新版本的VS2017,并安装.NET Core2.0中相关开发工具   2.打开VS2017,点击文件-新建-项目,选择.NET Core中的ASP.NET Core Web 应用程序   ...

  8. Bootstrap 按钮,图片,辅助类

    Bootstrap 按钮 任何带有 class .btn 的元素都会继承圆角灰色按钮的默认外观.但是 Bootstrap 提供了一些选项来定义按钮的样式,具体如下表所示: 以下样式可用于<a&g ...

  9. table 标签 语法

  10. 【bzoj4229】选择 离线+LCT

    题目描述 现在,我想知道自己是否还有选择. 给定n个点m条边的无向图以及顺序发生的q个事件. 每个事件都属于下面两种之一: 1.删除某一条图上仍存在的边 2.询问是否存在两条边不相交的路径可以从点u出 ...