green thread 绿色线程 纤程 native thread 主线程
小结:
1、纤程 : 启动、停止、主动让出自己的控制权yield;在用户空间实现多任务的处理。
2、纤程执行上下文的切换发生于用户空间,并且不是通过操作系统内核进行调度。这些因素导致了与线程相比,他们往往具有更高的执行效率。
3、Green Threads是在Native Thread在用户空间的模拟,它们常常用于无法将用户线程映射成为操作系统内核线程的环境之中,现在已经不常使用了。
Go运行时以将每一个Goroutine映射到一个OS本地线程池
https://en.wikipedia.org/wiki/Green_threads
A gentle introduction to multithreading - Internal Pointers https://www.internalpointers.com/post/gentle-introduction-multithreading
https://github.com/pro648/tips/blob/master/sources/多线程简述.md
到目前为止,提到的线程均是操作系统创建的。想要创建线程的进程必须与操作系统通信,但并非每个平台都原生支持线程。绿色线程(也称为光纤 fiber)是一种由运行环境或虚拟机调度,而不是由本地操作系统调度的线程,Green thread 并不依赖底层的系统功能,模拟实现了多线程的运行,这种线程的管理调度发生在用户空间,而非内核空间,所以 green thread 可以在没有原生线程支持的环境中工作。
由于绿色线程绕过了操作系统,其创建和管理速度更快,但也有缺点。下一篇文章并发控制之线程同步将介绍其缺点。
Green thread 名称来源于 Sun Microsystem 的 Green Team,Green team 在90年代设计了 Java 线程库。在2000年,Java 已经转移到原生多线程。Go、Haskell、Rust等语言仅实现了类似于绿色线程,用以代替原生线程。
Java的Green threads是Coroutine吗? - 圆胖肿的回答 - 知乎 https://www.zhihu.com/question/64100112/answer/1536482076
不是,是goroutine,或者尤其是unix/solaris下的goroutine,谷歌那些人跟java那些人其实都是斯坦福系的人马,很多东西都跟这批人有比较大的关系
为什么不是coroutine而是goroutine呢,从使用上说,它更接近goroutine,主要差异点并不是在实现上,实现上有多种方案,而且实现的差异对用户是透明的,用户真正注意到的应该是api,用法上的差异,coroutine和goroutine的主要用法差异就是后者比较难切换到native thread上去,就它强行让你用goroutine,不让你用thread,那当你要弄thread的时候,你就难受了
这个今天正好看到johan vos发的一个推,直接截图了
翻译一下,就是在早些那些黑暗的日子里,我们在linux的java上用green thread,我还记得需要切换回native thread原生线程时候的痛苦。时至今日,cpu已经进化了很多,绿色线程/green thread可以被考虑使用,我好奇今天有多少程序/人在使用它
下面回复很快就有人提出了fiber和虚拟线程以及loom项目,loom其实就是你所说的coroutine的对应java版本,当然会有细微的差异,但是我们不管那个细节上的差异,实际用途是一致的,我们只看目的,不看实现的手段,这也是johan vos在后面回复的内容,这些差异对于开发来说是透明的,所有的差异都被隐藏到api后去了,嗯,对,有好几种实现的方式
jenkov是著名的java tutorial的作者,写了很多入门的java代码案例,你用谷歌搜索java的example,很容易就会被引导到他的网站上去所以差异我们放到一边不说,我们来说一下johan vos所说的pain也就是痛苦是什么
就是你要切换到native thread的场景
那什么时候需要切换到native thread中去?
游戏,最常见的就是游戏客户端,比如opengl等渲染api对于线程是有要求的,很多操作只能在主线程或者是ui线程上操作,也许可以屏蔽掉一些实现的细节,但是一旦渲染的速度达到了游戏的要求,尤其是动作游戏,你很难不碰线程,因为这个时候你要处理图像,而且要快,这个时候只能在主线程上做,如果你切换到其他线程去操作ui上的组件,大部分gui都会直接提示你线程错误,这个不管是javafx还是flutter甚至swiftui都是一样,还包括安卓什么的,都有一个ui线程或者主线程的概念,只能在主线程或者ui线程上操作组件,而且代码处理起来还要快,不能堵着这个线程,你要分析一下时间复杂度,大概预估一下操作所使用的时间,一旦堵了,客户端软件就很卡了,一卡客户就骂娘了,这个其实做过app的人,应该都知道有这么一回事
后端/服务器/云端也有,vert.x就有类似要求,eventloop不能堵,而且eventloop必须是native thread,当然vert.x这个pain,主要是vert.x的实现者的pain,相比起游戏客户端,这个pain会被局限在vert.x实现者内部,而游戏的这个pain可能会连带着让使用者一起觉得pain
所以在语言层面,应该提供的是两种自由切换的方式,就像coroutine干的那样,你可以通过coroutine scope来切换成虚拟线程的scope范围,还有loom做的那样,loom可以选择用户的线程是不是virtual虚拟的,如果不是,那就是普通的native thread,如果是,那就是类似green thread的一个东西,所以就多了这个选择切换的权力
java在早期的实现里面,green thread是实现thread的一种方式,api并不像loom一样,会提供你自由选择或者切换的方式,thread.virtual这个方法,要等到loom毕业之后才会开放
所以green thread并不是loom,也不是coroutine,更像是goroutine,强迫你虚拟化,那时候你没有选择的权力
Green_threads
Java的Green threads是Coroutine吗? - ETIN的回答 - 知乎 https://www.zhihu.com/question/64100112/answer/218379442
Green Thread
Java语言刚刚引入之时将线程线程作为一个核心的概念,并且宣扬可以运行于所有的平台之上作为卖点,但是在这点上由于某些平台(譬如说早期的Solaris OS)没有提供本地线程的支持,无法将用户线程映射到OS线程。因此,需要在虚拟机平台之上模拟“内核线程”的概念。这些模拟出来的“线程”称之为“绿色线程”。“绿色线程”运行在用户空间,通过第三方library或者VM进行调度。操作系统内核线程认为它们都属于同一个进程,所以不能同时将他们调度在不同的CPU核心上处理。因此,绿色线程仅仅是一个并发的概念,但并没有实现真正意义上的并行。所以在后续的Java版本中,“绿色线程”就被1:1的线程映射模型所取代了。所以说,Green Threads是在Native Thread在用户空间的模拟,它们常常用于无法将用户线程映射成为操作系统内核线程的环境之中,现在已经不常使用了。
Fibers and Coroutine
线程是轻量级的进程,纤程是轻量级的线程,纤程在用户空间实现了多任务的协同处理,而并非通过内核级别的协同处理。纤程必须主动地yield自身的执行以便允许其他线程继续执行。纤程总是在许多预定义的地方启动、停止、yield。这使得编程更加容易,程序员只要保证他们的代码不会出现突然的中断并且数据结构不能被其他纤程访问到。但是纤程必须很好地进行主动的yield以便完成并发——因为它无法被操作系统内核代理。纤程有他们自己的栈空间,但是纤程执行上下文的切换发生于用户空间,并且不是通过操作系统内核进行调度。这些因素导致了与线程相比,他们往往具有更高的执行效率。纤程是一个并发的概念,也不是真正意义上的并行。每一个纤程都有一个父级线程,一个线程又从属于了一个进程。因此同一个线程中的多个纤程无法同时运行。换句话说,多个执行路径以纤程的方式并存,但它们无法在同一个时刻同时运行。纤程总是一些生存周期很短的任务,不像线程一样,它们往往有着较长的生存周期。因此,纤程拥有更小的栈空间。
为了避免引入第三方的线程库,有些编程语言引入了协程——Coroutine的概念,在语法层面实现了纤程的功能。纤程和协程描述了相同的概念,他们都不是真正意义上的并行。但是,它们能让你更容易地处理异步I/O的问题。我们可以在纤程或协程中发起I/O操作之后进行yield,以便在系统响应时间要求极短的UI操作之后唤醒,藉此提升用户体验。相比于另起一个后台线程来说这是一个更加高效和优雅的用法。
Goroutine
Goroutine是定义于Go语言概念。每一个Goroutine都作为一个函数异步执行。Go运行时以将每一个Goroutine映射到一个OS本地线程池的方式,既降低了线程阻塞的开销,又减小了上下文切换的开销。因此,GoLang作为一个首屈一指的M:N线程模型的高并发语言,未来不容小觑!