文字解说Golang Goroutine和线程的区别

目录
  • 一、Golang Goroutine?
  • 二、线程是什么?
  • 三、调度的区别
    • 1.线程调度
    • 2.goroutine 调度
  • 四、栈空间的区别
    • 1.线程占用
    • 2.goroutine 占用
  • 五、标识的区别
    • 1.线程标识
    • 2.goroutine 标识
  • 总结

Golang Goroutine和线程的区别 Golang,轻松学习

一、Golang Goroutine?

当使用者分配足够多的任务,系统能自动帮助使用者把任务分配到 CPU 上,让这些任务尽量并发运作。这种机制在 Go语言中被称为 goroutine。

goroutine 是 Go语言中的轻量级线程实现,由 Go 运行时(runtime)管理。Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU。

使用每一个 go 关键字将会额外开启一个新的协程 goroutine

二、线程是什么?

线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

三、调度的区别

1.线程调度

线程是系统调度的基本单位,线程作为调度与分配的基本单位,线程切换,仅需保存和设置少量寄存器的内容,开销远小于进程开销。但这种线程切换仍然需要一个完整的上下文切换:即保存一个线程的状态到内存,再恢复另外一个线程的状态,最后更新调度器的数据结构。某种意义上,这种操作还是很慢的。

2.goroutine 调度

Go运行的时候包涵一个自己的调度器,这个调度器使用一个称为一个M:N调度技术,m个goroutine到n个os线程(可以用GOMAXPROCS来控制n的数量),Go的调度器不是由硬件时钟来定期触发的,而是由特定的go语言结构来触发的,他不需要切换到内核语境,所以调度一个goroutine比调度一个线程的成本低很多。
Goroutine协程是一种协作任务控制机制,Goroutine可以理解为一种Go语言的协程。同时它可以运行在一个或多个线程上。而Goroutine协程的切换一般由程序员在代码中显式控制。它避免了上下文切换的额外耗费,兼顾了多线程的优点,简化了高并发程序的复杂。

四、栈空间的区别

1.线程占用

每个OS的线程都有一个固定大小的栈内存,通常是2MB,栈内存用于保存在其他函数调用期间哪些正在执行或者临时暂停的函数的局部变量。这个固定的栈大小,如果对于goroutine来说,可能是一种巨大的浪费。
以 64位环境的 JVM 为例,会默认固定为每个线程分配 1MB 栈空间,如果大小分配不当,便会出现栈溢出的问题。

2.goroutine 占用

- goroutine 所占用的内存,均在栈中进行管理 - goroutine 所占用的栈空间大小,由 runtime 按需进行分配 goroutine在生命周期开始只有一个很小的栈,典型情况是2KB, 在go程序中,一次创建十万左右的goroutine也不罕见(2KB*100,000=200MB)。而且goroutine的栈不是固定大小,它可以按需增大和缩小,最大限制可以到1GB。 goroutine 相较于线程更加轻量,关键点就在于栈空间的动态分配,这样便可以最大限度的利用内存资源。

五、标识的区别

1.线程标识

在大部分支持多线程的操作系统和编程语言中,线程有一个独特的标识,通常是一个整数或者指针,这个特性可以让我们构建一个线程的局部存储,本质是一个全局的map,以线程的标识作为键,这样每个线程可以独立使用这个map存储和获取值,不受其他线程干扰。

2.goroutine 标识

goroutine中没有可供程序员访问的标识,原因是一种纯函数的理念,不希望滥用线程局部存储导致一个不健康的超距作用,即函数的行为不仅取决于它的参数,还取决于运行它的线程标识。

总结

Golang 通过复杂的协程操作来实现我们的并发需求,golang是用户线程与系统线程的对应关系是多对多,既能利用多核cpu资源,也能尽可能减少上下文切换成本,代价是go需要实现复杂的goroutine调度机制。
相比于N:1时所有用户线程对应1个系统线程,无法利用多核cpu;1:1时1个用户线程对应一个系统线程,上下文切换成本高。通过复杂的调度实现N:N时,即能利用多核cpu资源,也能尽可能减少上下文切换成本,成为Go语言最为人知的特点,天生支持高并发与高效。

到此这篇关于Golang Goroutine和线程的区别的文章就介绍到这了,更多相关Golang Goroutine和线程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • golang 阻止主goroutine退出的操作

    1:for //使用无线循环 for{ } 如果想退出 for { reutrn } 例如:启动三个 goroutine 等待三个 goroutine 执行结束一下 退出主 goroutine var c bool = false var nums int = 0 for i := 0; i < 3; i++ { go func() { fmt.Println("begin------------end") time.Sleep(10 * time.Second) nums++

  • Golang Goroutine的使用

    什么是 Goroutine goroutine 是 Go 并行设计的核心.goroutine 说到底其实就是协程,它比线程更小,十几个 goroutine 可能体现在底层就是五六个线程,Go 语言内部帮你实现了这些 goroutine 之间的内存共享. 执行 goroutine 只需极少的栈内存(大概是4~5KB),当然会根据相应的数据伸缩.也正因为如此,可同时运行成千上万个并发任务.goroutine 比 thread 更易用.更高效.更轻便. 一般情况下,一个普通计算机跑几十个线程就有点负载

  • 解决Golang中goroutine执行速度的问题

    突然想到了之前一直没留意的for循环中开goroutine的执行顺序问题,就找了段代码试了试,试了几次后发现几个有意思的地方,我暂时没有精力往更深处挖掘,希望有golang大神能简单说一说这几个地方是怎么回事. 代码: package main import "fmt" func Count(ch chan int) { fmt.Println("Count doing") ch <- 1 fmt.Println("Counting") }

  • 关于golang利用channel和goroutine完成统计素数的思路

    1. 需求 要求统计1-200000的数字中,哪些是素数?这个问题在本章开篇就提出来了,可以使用goroutine和channel来完成 2.分析思路 传统的方法,就是使用一个循环,循环的判断各个数是不是素数[ok] 使用并发/并行的方式,将统计素数的任务分配给多个(x个)goroutine去完成,完成任务时间短 分析思路图:  代码实现: package main import ( "fmt" "time" ) // 需求: // 要求统计1-200000的数字,

  • golang goroutine顺序输出方式

    range字符串,使用goroutine打印 因为goroutine随机执行 for _, v := range str { go func() { fmt.Println(string(v)) }() } 输出: 5 5 5 5 5 可以使用chan顺序输出 for _, c := range str{ ch := make(chan rune) go func(ch <-chan rune) { key := <-ch fmt.Println(string(key)) }(ch) ch &

  • Golang 语言控制并发 Goroutine的方法

    goroutine 是 Go语言中的轻量级线程实现,由 Go 运行时(runtime)管理.Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU. 01介绍 Golang 语言的优势之一是天生支持并发,我们在 Golang 语言开发中,通常使用的并发控制方式主要有 Channel,WaitGroup 和 Context,本文我们主要介绍一下 Golang 语言中并发控制的这三种方式怎么使用?关于它们各自的详细介绍在之前的文章已经介绍过,感兴趣的读者朋友们可以按需翻阅. 02

  • 文字解说Golang Goroutine和线程的区别

    目录 一.Golang Goroutine? 二.线程是什么? 三.调度的区别 1.线程调度 2.goroutine 调度 四.栈空间的区别 1.线程占用 2.goroutine 占用 五.标识的区别 1.线程标识 2.goroutine 标识 总结 Golang Goroutine和线程的区别 Golang,轻松学习 一.Golang Goroutine? 当使用者分配足够多的任务,系统能自动帮助使用者把任务分配到 CPU 上,让这些任务尽量并发运作.这种机制在 Go语言中被称为 gorout

  • 深入浅析WinForm 进程、线程及区别介绍

    一.进程 进程是一个具有独立功能的程序关于某个数据集合的一次运行活动. 它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体. Process 类,用来操作进程. 命名空间:using System.Diagnostics; Process.Start("calc"); //打开计算器 Process.Start("mspaint"); //打开画图 Process.Start("iexplore" , "http://www.

  • Golang与python线程详解及简单实例

    Golang与python线程详解及简单实例 在GO中,开启15个线程,每个线程把全局变量遍历增加100000次,因此预测结果是 15*100000=1500000. var sum int var cccc int var m *sync.Mutex func Count1(i int, ch chan int) { for j := 0; j < 100000; j++ { cccc = cccc + 1 } ch <- cccc } func main() { m = new(sync.

  • C#中前台线程和后台线程的区别与联系

    前台线程和后台线程的区别和联系: 1.后台线程不会阻止进程的终止.属于某个进程的所有前台线程都终止后,该进程就会被终止.所有剩余的后台线程都会停止且不会完成. 2.可以在任何时候将前台线程修改为后台线程,方式是设置Thread.IsBackground 属性. 3.不管是前台线程还是后台线程,如果线程内出现了异常,都会导致进程的终止. 4.托管线程池中的线程都是后台线程,使用new Thread方式创建的线程默认都是前台线程. 下面做个小例子来证实一下,代码如下很简单: class Progra

  • Python中进程和线程的区别详解

    Num01–>线程 线程是操作系统中能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位. 一个线程指的是进程中一个单一顺序的控制流. 一个进程中可以并发多条线程,每条线程并行执行不同的任务. Num02–>进程 进程就是一个程序在一个数据集上的一次动态执行过程. 进程有以下三部分组成: 1,程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成. 2,数据集:数据集则是程序在执行过程中需要的资源,比如图片.音视频.文件等. 3,进程控制块:进程控制块是用来记录进程的外部

  • c# 进程和线程的区别与联系

    引入线程是为了减少程序在并发执行时所付出的时空开销. 属性: 轻型实体.它不拥有系统资源,只是有一点必不可少的.能保证独立运行的资源. 独立调度和分派的基本单位.在多线程OS中,线程是独立运行的基本单位,因而也是独立调度和分派的基本单位,但由于线程很轻,故线程的切换非常迅速且开销小. 可并发执行.在一个进程中的多个线程之间可以并发执行,甚至允许在一个进程中的所有线程都能并发执行:同样,不同进程中的线程也能并发执行. 共享进程资源.在同一个进程中的各个线程都可以共享该进程所拥有的资源,这首先表现在

  • Java守护线程和用户线程的区别

    目录 守护线程定义 创建守护线程 将线程池设置为守护线程 守护线程 VS 用户线程 用户线程 守护线程 守护线程注意事项 总结 前言: 在 Java 语言中,线程分为两类:用户线程和守护线程,默认情况下我们创建的线程或线程池都是用户线程,所以用户线程也被称之为普通线程. 想要查看线程到底是用户线程还是守护线程,可以通过 Thread.isDaemon() 方法来判断,如果返回的结果是 true 则为守护线程,反之则为用户线程. 我们来测试一下默认情况下线程和线程池属于哪种线程类型?测试代码如下:

  • python浅析守护线程与非守护线程的区别与使用

    目录 什么是守护线程 非守护线程 守护线程 什么是守护线程 当主线程执行结束后,所有 在运行的子线程都 直接结束,不管子任务是否完成 很多语言的 垃圾收集器 就运用了 守护线程,去回收程序不再使用的垃圾内存 而非守护线程其实就跟守护线程相反,当主线程结束后,如果子线程还在运行,子线程并不会直接结束,而是 继续完成任务,等待子线程都执行完毕才结束 非守护线程 下面是一个普通线程的例子,也就是 非守护线程 我们创建了 autofelix 购物线程,去模拟购物流程的任务 可以看出当主线程已经结束,但是

随机推荐