Golang:线程 和 协程 的区别

Posted linguanh

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Golang:线程 和 协程 的区别相关的知识,希望对你有一定的参考价值。

目录

第 1第 2

前言

草稿线程和协程的区别及其关系

协程

Coroutinegorutine多任务并发作业多线程
依赖于线程

下面我们来看看它们的区别。

线程的基础介绍,这里请自行网上搜索文章,因为关于线程的优秀介绍文章已经很多。

协程的特点

这里先直接列出线程的特点,然后从例子中进行解析。

协程的调度
第 1第 2

我们来看一个例子:

func TestGorutine(t *testing.T) 
    runtime.GOMAXPROCS(1)  // 指定最大 P 为 1,从而管理协程最多的线程为 1 个
    wg := sync.WaitGroup // 控制等待所有协程都执行完再退出程序
    wg.Add(2)
    // 运行一个协程
    go func() 
        fmt.Println(1)
        fmt.Println(2)
        fmt.Println(3)
        wg.Done()
    ()

    // 运行第二个协程
    go func() 
        fmt.Println(65)
        fmt.Println(66)
        // 设置个睡眠,让该协程执行超时而被挂起,引起超时调度
        time.Sleep(time.Second)
        fmt.Println(67)
        wg.Done()
    ()
    wg.Wait()
顺序是交错
65
66
1
2
3
67
随时中断
纯应用态的协程调度

关于上述代码中,为什么要指定下面两行代码?

runtime.GOMAXPROCS(1)
time.Sleep(time.Second)

这需要您去看下 Go 的协程调度入门基础,请看我之前的另外一篇调度分析文章:

runtime.GOMAXPROCS(1)分配到不同的线程

协程特点中的第 3 和 第 4 点。

  1. 执行效率高。
  2. 占用内存少。
协程的调度切换不是线程切换没有线程切换的开销

内存的花销,使用其所在的线程的内存,意味着线程的内存可以供多个协程使用。

不需要多线程的锁机制不存在同时写变量冲突

和线程的整体对比

比较的点 线程 协程
数据存储 内核态的内存空间 一般是线程提供的用户态内存空间
切换操作 操作最终在内核层完成,应用层需要调用内核层提供的 syscall 底层函数 应用层使用代码进行简单的现场保存和恢复即可
任务调度 由内核实现,抢占方式,依赖各种锁 由用户态的实现的具体调度器进行。例如 go 协程的调度器
语音支持程度 绝大部分编程语言 部分语言:Lua,Go,Python ...
实现规范 按照现代操作系统规范实现 无统一规范。在应用层由开发者实现,高度自定义,比如只支持单线程的线程。不同的调度策略,等等

以上是关于Golang:线程 和 协程 的区别的主要内容,如果未能解决你的问题,请参考以下文章