浅析Java的线程和Golang的协程
Java的多线程
- 线程是程序执行中一个
单一的顺序控制流程
,是程序执行流的最小单元
,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,Java的多线程是通过JMM(共享内存模型)
来实现的。 - 大部分的操作系统都是利用
时间片轮转的抢占式调度方式
,线程需要利用操作系统的调度算法在用户态和内核态来回切换,线程的切换是非常浪费资源的,所以Java的线程池在工作中才那么常用,也是面试中无法绕过的坎。 - 程序一般不会直接去使用内核线程,而是去使用内核线程的一种高级接口——
轻量级进程(Lightweight Process,LWP)
,轻量级进程就是我们通常意义上所讲的线程,也被叫做用户线程。
线程的实现模型
- 一对一模型
一个用户线程对应一个内核线程,如果是多核的 CPU,那么线程之间是真正的并发。
缺点:
内核线程的数量有限,一对一模型使用的用户线程数量有限制。
内核线程的调度,上下文切换的开销较大(虽然没有进程上下文切换的开销大),导致用户线程的执行效率下降。
- 多对一模型
多个用户线程映射到一个内核线程上,线程间的切换由用户态的代码来进行。用户线程的建立、同步、销毁都是在用户态中完成,不需要内核的介入。因此多对一的上下文切换速度快很多,且用户线程的数量几乎没有限制。
缺点:
若一个用户线程阻塞,其他所有线程都无法执行,此时内核线程处于阻塞状态。
处理器数量的增加,不会对多对一模型的线程性能造成影响,因为所有的用户线程都映射到了一个处理器上。
- 多对多模型
结合了一对一模型和多对一模型的优点,多个用户线程映射到多个内核线程上,由线程库负责在可用的可调度实体上调度用户线程。这样线程间的上下文切换很快,因为它避免了系统调用。但是增加了系统的复杂性。
优点:
一个用户线程的阻塞不会导致所有线程的阻塞,因为此时还有别的内核线程被调度来执行;
多对多模型对用户线程的数量没有限制;
在多处理器的操作系统中,多对多模型的线程也能得到一定的性能提升,但提升的幅度不如一对一模型的高。
Java实现多线程
在Java中创建线程的方式有很多种,那么就写一个平时工作中最常见的方式,也就是上面提到的线程池。
public ExecutorService asyncExecutor() {return new ThreadPoolExecutor(100, 200, 10,TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), new NamedThreadFactory(ASYNC_NAME + "-"));}
使用方法如下:
@Resource(name = "asyncExecutor")private ExecutorService executor;executor.execute();
Golang的协程
- 和Java不同的是协程不需要通过共享内存来通信,而是通过通信来共享内存。
- 协程也并不是Golang提出来的,协程是一种编程思想,并不局限于特定的语言。Go、Python、Kotlin都可以在语言层面上实现协程,Java 也可以通过扩展库的方式间接支持协程。协程比线程更加轻量级,可以由程序员自己管理的轻量级线程,对内核不可见。
- Golang为构建并发程序的基本代码块是:协程 (goroutine) 与通道 (channel)。他们需要语言,编译器,和 runtime 的支持。
协程的原理
当出现IO阻塞的时候,由协程的调度器进行调度,通过将数据流立刻yield掉(主动让出),并且记录当前栈上的数据,阻塞完后立刻再通过线程恢复栈,并把阻塞的结果放到这个线程上去跑,这样看上去好像跟写同步代码没有任何差别,这整个流程可以称为coroutine,而跑在由coroutine负责调度的线程称为Fiber。比如Golang里的 go关键字其实就是负责开启一个Fiber,让func逻辑跑在上面。
由于协程的暂停完全由程序控制,发生在用户态上;而线程的阻塞状态是由操作系统内核来进行切换,发生在内核态上。
因此,协程的开销远远小于线程的开销,也就没有了 ContextSwitch 上的开销。
假设程序中默认创建两个线程为协程使用,在主线程中创建协程ABCD…,分别存储在就绪队列中,调度器首先会分配一个工作线程A执行协程A,另外一个工作线程B执行协程B,其它创建的协程将会放在队列中进行排队等待。
当协程A调用暂停方法或被阻塞时,协程A会进入到挂起队列,调度器会调用等待队列中的其它协程抢占线程A执行。当协程A被唤醒时,它需要重新进入到就绪队列中,通过调度器抢占线程,如果抢占成功,就继续执行协程A,失败则继续等待抢占线程。
总结
- Java 在 Linux 操作系统下使用的是用户线程+轻量级线程,一个用户线程映射到一个内核线程,线程之间的切换就涉及到了上下文切换。所以在 Java 中并不适合创建大量的线程,否则效率会很低。
- 对Java而言,操作系统会分配一块默认1M大小的栈,如果深度递归可能出现栈大小不足,但是如果一次性分配更大的内存又有可能出现浪费的现象;协程开始的时候也会分配一定大小的内存区域,一般只有2K,和线程的栈一样,协程的栈存储的也是局部变量,但是不同的是协程的栈的大小是不固定的,是可以根据需要自动调整大小的,最大甚至可以达到1G,所以灵活性非常好。
- 上面也说到Java线程需要在用户态和内核态来回切换,这样子就会很浪费资源;但是协程只是用户态。
- 协程适合于阻塞IO,对于CPU计算密集型的协程也不能很好解决。
本文只是从原理、应用场景来分析一下线程和协程的区别。
浅析Java的线程和Golang的协程相关推荐
- golang异步协程调度原理
golang异步协程调度 在1.14的go版本中,官方通过加入信号来进行协程的调度,后续就都支持了这种异步协程抢占,避免了早起的考栈调度时来检查是否执行超时的逻辑.本文简单来对比这种实现的原理. 调度 ...
- 线程,进程,协程详细解释
什么是进程和线程 进程是什么呢? 直白地讲,进程就是应用程序的启动实例.比如我们运行一个游戏,打开一个软件,就是开启了一个进程. 进程拥有代码和打开的文件资源.数据资源.独立的内存空间. 线程又是什么 ...
- golang goroutine协程运行机制及使用详解
Go(又称Golang)是Google开发的一种静态强类型.编译型.并发型,并具有垃圾回收功能的编程语言.Go于2009年正式推出,国内各大互联网公司都有使用,尤其是七牛云,基本都是golang写的, ...
- k8s与监控--从telegraf改造谈golang多协程精确控制
从telegraf改造谈golang多协程精确控制 前言 telegraf是infuxdb公司开源出来的一个基于插件机制的收集metrics的 项目.整个架构和elastic公司的日志收集系统极其类似 ...
- Golang的协程调度
调度的基础,模型关系的映射 GPM模型: G,Goroutinue 被调度器管理的轻量级线程,goroutine使用go关键字创建 调度系统的最基本单位goroutine,存储了goroutine的执 ...
- Golang的协程调度器原理及GMP设计思想
一.Golang"调度器"的由来? (1) 单进程时代不需要调度器 我们知道,一切的软件都是跑在操作系统上,真正用来干活(计算)的是CPU.早期的操作系统每个程序就是一个进程,知道 ...
- Python中的线程、进程、协程以及区别
进程,是执行中的计算机程序.也就是说,每个代码在执行的时候,首先本身即是一个进程.一个进程具有:就绪,运行,中断,僵死,结束等状态(不同操作系统不一样). 运行中每个进程都拥有自己的地址空间.内存.数 ...
- Python 线程和进程和协程总结
Python 线程和进程和协程总结 线程和进程和协程 进程 进程是程序执行时的一个实例,是担当分配系统资源(CPU时间.内存等)的基本单位: 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其 ...
- Python之路,Day9 - 线程、进程、协程和IO多路复用
参考博客: 线程.进程.协程: http://www.cnblogs.com/wupeiqi/articles/5040827.html http://www.cnblogs.com/alex3714 ...
- 教你打开线程、进程和协程的大门!
作者 | 蓝 责编 | 张文 头图 | CSDN 下载自视觉中国 不知从几何起,可能是大三那年的操作系统考试,也可能是刚经历完的秋招,这些概念总是迷迷糊糊,可能自己回答的和其他人的答复也差不多,并没 ...
最新文章
- python3自动释放线程_Python3高级特性:并发
- Docker中运行EOS FOR MAC
- android 上下滚动文字_android高仿今日头条富文本编辑(发布文章)
- ionic上拉加载-下拉刷新
- 阿里数据库内核月报:2015年11月
- 基于时序数据库做监控,这里有超流行的开源方案
- bzoj 1753: [Usaco2005 qua]Who's in the Middle【排序】
- [MEGA DEAL]完整的Java捆绑包(96%折扣)
- java private是什么_java private 干什么用
- epplus word html,EPPlus简介
- 竞拍网站服务器配置,GOM引擎新区竞拍脚本,GOM传奇服务端设置竞拍的方法和教程...
- 用VBS脚本实现软件定条件开启
- Arduino控制PS2无线手柄
- 苹果x与苹果xs的区别_x和XS的区别到底在哪里,我来告诉你
- js获取剪切板文字图片方法
- 亚瑟阿伦的三十六个问题。
- 从图片到涂鸦:高品质涂鸦的自动生成
- 群体药动学药效学模型
- 支付宝电脑网页支付接口的调用
- 人工智能实战2019 第五次作业 焦宇恒 16721088