码迷,mamicode.com
首页 > 其他好文 > 详细

什么是协程

时间:2018-12-06 00:04:08      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:暂停   为什么   轻量级   消费   cer   定义   开始   应该   cpu   

技术分享图片

 

 

技术分享图片

 

 

—————  第二天  —————

 

 

技术分享图片

 

 

技术分享图片

 

 

技术分享图片

 

 

技术分享图片

 

 

技术分享图片

 

 

————————————

 

 

技术分享图片

技术分享图片

 

 

技术分享图片

 

 

技术分享图片

 

 

技术分享图片

 

 

技术分享图片

 

 

 

什么是进程和线程

 

 

有一定基础的小伙伴们肯定都知道进程和线程。

 

进程是什么呢?

 

直白地讲,进程就是应用程序的启动实例。比如我们运行一个游戏,打开一个软件,就是开启了一个进程。

 

进程拥有代码和打开的文件资源、数据资源、独立的内存空间。

 

线程又是什么呢?

 

线程从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。

 

线程拥有自己的栈空间。

 

 

 

技术分享图片

 

 

 

有人给出了很好的归纳:

 

对操作系统来说,线程是最小的执行单元,进程是最小的资源管理单元。

 

 

无论进程还是线程,都是由操作系统所管理的。

 

Java中线程具有五种状态:

 

初始化

可运行

运行中

阻塞

销毁

 

这五种状态的转化关系如下:

 

 

技术分享图片

 

 

但是,线程不同状态之间的转化是谁来实现的呢?是JVM吗?

 

并不是。JVM需要通过操作系统内核中的TCB(Thread Control Block)模块来改变线程的状态,这一过程需要耗费一定的CPU资源。

 

 

技术分享图片

 

 

技术分享图片

 

 

 

进程和线程的痛点

 

线程之间是如何进行协作的呢?

 

最经典的例子就是生产者/消费者模式

 

若干个生产者线程向队列中写入数据,若干个消费者线程从队列中消费数据。

 

 

 

技术分享图片

 

 

如何用java语言实现生产者/消费者模式呢?

 

让我们来看一看代码:

 

 

 

public class ProducerConsumerTest {

技术分享图片

}

class Producer extends Thread {

技术分享图片

}

class Consumer extends Thread { private final QueuesharedQueue;

技术分享图片

}


这段代码做了下面几件事:

1.定义了一个生产者类,一个消费者类。

2.生产者类循环100次,向同步队列当中插入数据。

3.消费者循环监听同步队列,当队列有数据时拉取数据。

4.如果队列满了(达到5个元素),生产者阻塞。

5.如果队列空了,消费者阻塞。

 

上面的代码正确地实现了生产者/消费者模式,但是却并不是一个高性能的实现。为什么性能不高呢?原因如下:

 

1.涉及到同步锁。

2.涉及到线程阻塞状态和可运行状态之间的切换。

3.涉及到线程上下文的切换。

 

以上涉及到的任何一点,都是非常耗费性能的操作。

 

技术分享图片

 

 

技术分享图片

 

 

 

什么是协程

 

协程,英文Coroutines,是一种比线程更加轻量级的存在。正如一个进程可以拥有多个线程一样,一个线程也可以拥有多个协程。

 

 

 

技术分享图片

 

 

最重要的是,协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)。

 

这样带来的好处就是性能得到了很大的提升,不会像线程切换那样消耗资源。

 

既然协程这么好,它到底是怎么来使用的呢?

 

由于Java的原生语法中并没有实现协程(某些开源框架实现了协程,但是很少被使用),所以我们来看一看python当中对协程的实现案例,同样以生产者消费者模式为例:

 

 

技术分享图片

 

 

这段代码十分简单,即使没用过python的小伙伴应该也能基本看懂。

 

代码中创建了一个叫做consumer的协程,并且在主线程中生产数据,协程中消费数据。

 

其中 yield 是python当中的语法。当协程执行到yield关键字时,会暂停在那一行,等到主线程调用send方法发送了数据,协程才会接到数据继续执行。

 

但是,yield让协程暂停,和线程的阻塞是有本质区别的。协程的暂停完全由程序控制,线程的阻塞状态是由操作系统内核来进行切换。

 

因此,协程的开销远远小于线程的开销。

 

 

技术分享图片

 

 

技术分享图片

 

 

 

协程的应用

 

有哪些编程语言应用到了协程呢?我们举几个栗子:

 

Lua语言

Lua从5.0版本开始使用协程,通过扩展库coroutine来实现。

 

Python语言

正如刚才所写的代码示例,python可以通过 yield/send 的方式实现协程。在python 3.5以后, async/await 成为了更好的替代方案。

 

Go语言

Go语言对协程的实现非常强大而简洁,可以轻松创建成百上千个协程并发执行。

 

Java语言

如上文所说,Java语言并没有对协程的原生支持,但是某些开源框架模拟出了协程的功能,有兴趣的小伙伴可以看一看Kilim框架的源码:

https://github.com/kilim/kilim

 

 

 

技术分享图片

 

什么是协程

标签:暂停   为什么   轻量级   消费   cer   定义   开始   应该   cpu   

原文地址:https://www.cnblogs.com/wlemory/p/10074155.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!