Go语言的并发和并行

  不知道你有没有注意到,这段代码如果我跑在两个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不阻塞

时间: 2024-09-30 00:19:47

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

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

目录(?) [-] Go语言并发的设计模式和应用场景 生成器 服务化 多路复合 select监听信道 结束标志 菊花链 随机数生成器 定时器 TODO Go语言并发的设计模式和应用场景 以下设计模式和应用场景来自Google IO上的关于Goroutine的PPT:https://talks.golang.org/2012/concurrency.slide 本文的示例代码在: https://github.com/hit9/Go-patterns-with-channel 生成器 在Pytho

Python并发与并行的新手指南

点这里 在批评Python的讨论中,常常说起Python多线程是多么的难用.还有人对 global interpreter lock(也被亲切的称为“GIL”)指指点点,说它阻碍了Python的多线程程序同时运行.因此,如果你是从其他语言(比如C++或Java)转过来的话,Python线程模块并不会像你想象的那样去运行.必须要说明的是,我们还是可以用Python写出能并发或并行的代码,并且能带来性能的显著提升,只要你能顾及到一些事情.如果你还没看过的话,我建议你看看Eqbal Quran的文章<

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

Python 多线程教程:并发与并行 在批评Python的讨论中,常常说起Python多线程是多么的难用.还有人对 global interpreter lock(也被亲切的称为“GIL”)指指点点,说它阻碍了Python的多线程程序同时运行.因此,如果你是从其他语言(比如C++或Java)转过来的话,Python线程模块并不会像你想象的那样去运行.必须要说明的是,我们还是可以用Python写出能并发或并行的代码,并且能带来性能的显著提升,只要你能顾及到一些事情.如果你还没看过的话,我建议你看看

转一篇关于并发和并行概念的好文,附带大神评论

转自:https://laike9m.com/blog/huan-zai-yi-huo-bing-fa-he-bing-xing,61/ 还在疑惑并发和并行? OK,如果你还在为并发(concurrency)和并行(parallesim)这两个词的区别而感到困扰,那么这篇文章就是写给你看的.搞这种词语辨析到底有什么意义?其实没什么意义,但是有太多人在混用错用这两个词(比如遇到的某门课的老师).不论中文圈还是英文圈,即使已经有数不清的文章在讨论并行vs并发,却极少有能讲清楚的.让一个讲不清楚的人来

并发与并行(concurrency vs parallesim)

最近对计算机中并发(concurrency)和并行(parallesim)这两个词的区别很迷惑,将搜索到的相关内容整理如下. http://www.vaikan.com/docs/Concurrency-is-not-Parallelism/#slide-7 定义: 并发 Concurrency 将相互独立的执行过程综合到一起的编程技术. 并行 Parallelism 同时执行(通常是相关的)计算任务的编程技术. 并发 vs. 并行 并发是指同时处理很多事情. 而并行是指同时能完成很多事情. 两

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

本文主要讲解Scala的并发(并行)编程,那么为什么题目概称geotrellis使用(六)呢,主要因为本系列讲解如何使用Geotrellis,具体前几篇博文已经介绍过了.我觉得干任何一件事情基础很重要,就像当年参加高考或者各种考试一样,老师都会强调基础,这是很有道理的.使用Geotrellis框架的基础就是Scala和Spark,所以本篇文章先来介绍一下Scala编程语言,同样要想搞明白Scala并发(并行)编程,Scala基础也很重要,没有Scala语言基础就谈不上Scala并发编程也就更谈不

异步,并发,并行的解释

异步 异步表明事情相互独立地发生,除非有强加的依赖性.生活也是异步的.这里的依赖性是大自然补充的,彼此互不相干的事情能够同时发生. 异步带来的最大复杂性就是如果你没有同时执行多个活动,那么异步就没有任何优势,如果你开始了一个异步活动,然后什么也不做就等他结束的话,那么你并没有从异步这里获得任何好处. 并发 并发的意思是指事情同时放生.并发是指实际上可能串行发生的事情好像同时发生一样.并发描述了单处理器系统中线程或进程的行为特点.在POSIX中,并发的定义要求"延迟调用线程的函数不应该导致其他线程

Go语言之并发

Go语言直接支持内置支持并发.当一个函数创建为goroutine时,Go会将其视为一个独立的工作单元.这个单元会被调度到可用的逻辑处理器上执行. Go语言运行时的调度器是一个复杂的软件,这个调度器在操作系统之上.操作系统的线程与语言运行时的逻辑处理器绑定,并在逻辑处理器上运行goroutine. Go语言的并发同步逻辑来自一个叫做通信顺讯进程(CSP)的范型.CSP是一种消息传递模型,通过在goroutine之间传递数据来传递消息,而不是通过对数据进行加锁来实现同步访问.这种数据的类型叫做通道(

[Go] 并发和并行的区别

并发和并行的区别:1.并行是让不同的代码片段同时在不同的物理机器上运行,并行的关键是在不同的物理机器上同时运行 2.并发是同时管理很多事情,比如在一个物理机器上进行不停的调度,有些事情可能只做了一半就被暂停去做别的事情了 3.因为操作系统和硬件总资源一般很少,所以并发的重要性更高,使用较少的资源做更多的事情的哲学也是指导Go语言设计的哲学 原文地址:https://www.cnblogs.com/taoshihan/p/10347104.html