您现在的位置是:群英 > 开发技术 > 编程语言
在golang里面线程和协程的区别是什么呢?
Admin发表于 2022-05-19 17:44:11897 次浏览
这篇文章给大家分享的是“在golang里面线程和协程的区别是什么呢?”,文中的讲解内容简单清晰,对大家认识和了解都有一定的帮助,对此感兴趣的朋友,接下来就跟随小编一起了解一下“在golang里面线程和协程的区别是什么呢?”吧。



区别:线程中数据存储在内核态的内存空间;而协程中数据存储在线程提供的用户态内存空间。线程的任务调度由内核实现,抢占方式,依赖各种锁;协程的任务调度由用户态实现的具体调度器进行。

本教程操作环境:windows10系统、GO 1.11.2、thinkpad t480电脑。

协程
协程,英文名Coroutine。但在 Go 语言中,协程的英文名是:gorutine。它常常被用于进行多任务,即并发作业。没错,就是多线程作业的那个作业。

虽然在 Go 中,我们不用直接编写线程之类的代码来进行并发,但是 Go 的协程却依赖于线程来进行。

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

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

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

  • 多个协程可由一个或多个线程管理,协程的调度发生在其所在的线程中。

  • 可以被调度,调度策略由应用层代码定义,即可被高度自定义实现。

  • 执行效率高。

  • 占用内存少。

上面第 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()}

上面的代码片段跑了两个协程,运行后,观察输出的顺序是交错的。可能是:

656612367

意味着在执行协程A的过程中,可以随时中断,去执协程行B,协程B也可能在执行过程中中断再去执行协程A。
看起来协程A 和 协程B 的运行像是线程的切换,但是请注意,这里的 A 和 B都运行在同一个线程里面。它们的调度不是线程的切换,而是纯应用态的协程调度。
关于上述代码中,为什么要指定下面两行代码?

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

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

如果不设置 runtime.GOMAXPROCS(1),那么程序将会根据操作系统的 CPU 核数而启动对应数量的 P,导致多个 M,即线程的启动。那么我们程序中的协程,就会被分配到不同的线程里面去了。为了演示,故设置数量 1,使得它们都被分配到了同一个线程里面,存于线程的协程队列里面,等待被执行或调度。

协程特点中的第 3和第 4点。
3. 执行效率高。
4. 占用内存少。

因为协程的调度切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。调度发生在应用态而非内核态。

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

其次协程的调度不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,所以执行效率比多线程高很多。

协程和线程的整体对比

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

推荐学习:Golang教程

以上就是golang中线程和协程的区别是什么的详细内容,更多请关注php中文网其它相关文章!



    感谢各位的阅读,以上就是“在golang里面线程和协程的区别是什么呢?”的内容了,通过以上内容的阐述,相信大家对在golang里面线程和协程的区别是什么呢?已经有了进一步的了解,如果想要了解更多相关的内容,欢迎关注群英网络,群英网络将为大家推送更多相关知识点的文章。

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

    标签: Golang
    相关信息推荐
    2022-08-26 17:48:31 
    摘要:本篇文章主要介绍了Java实现文件分割和文件合并实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2022-06-06 17:11:16 
    摘要:下面由golang教程栏目给大家介绍Golang连接池的几种实现案例,希望对需要的朋友有所帮助!因为TCP的三次握手等等原因,建立一个连接是一件成本比较高的行为。所以在一个需要多次与特定实体交互的程序中...
    2022-05-27 18:02:29 
    摘要:完全卸载Java的方法:首先将之前配置的环境变量删掉;然后正常卸载JavaSE;接着删除C盘中跟Java有关的文件夹;最后删除注册表并重启电脑即可。
    云活动
    推荐内容
    热门关键词
    热门信息
    群英网络助力开启安全的云计算之旅
    立即注册,领取新人大礼包
    • 联系我们
    • 24小时售后:4006784567
    • 24小时TEL :0668-2555666
    • 售前咨询TEL:400-678-4567

    • 官方微信

      官方微信
    Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
    增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
    免费拨打  400-678-4567
    免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
    微信公众号
    返回顶部
    返回顶部 返回顶部