前言:
现在朋友们对“python线程进程协程的区别”大体比较珍视,姐妹们都需要分析一些“python线程进程协程的区别”的相关资讯。那么小编同时在网络上汇集了一些对于“python线程进程协程的区别””的相关文章,希望我们能喜欢,我们一起来学习一下吧!什么是线程
线程是操作系统能够进行运算调度的最小单位。大部分情况下,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
在一些系统中,线程也被称之为轻量进程。而轻量进程一般指的内核线程。
一个进程可以有很多线程来处理,每条线程并行执行不同的任务。如果进程要完成的任务很多,这样需很多线程,也要调用很多核心。因此在多核的CPU上面使用多线程程序设计能更有效地利用CPU。
多线程示例:
@Test public void testThread() { Thread thread1 = new Thread(() -> funA(),"Thread-1"); Thread thread2 = new Thread(() -> funB(),"Thread-2"); Thread thread3 = new Thread(() -> funC(),"Thread-3"); thread1.start(); thread2.start(); thread3.start(); } public void funA() { System.out.println("A1"); System.out.println("A2"); System.out.println("A3"); } public void funB() { System.out.println("B1"); System.out.println("B2"); System.out.println("B3"); } public void funC() { System.out.println("C1"); System.out.println("C2"); System.out.println("C3"); }
运行结果:
A1C1C2C3B1A2A3B2B3
线程调度示意图:
如上图,一个线程绑定一个任务,任务会在CPU内执行,在Windows和Liunx等系统中,任务的调度采用的时间片强占调用方式。任务的状态分为运行状态和就绪状。举个例子,当任务1进行到就绪状态时,就会进行中断处理,并保存当前任务相关的执行信息(存在内存中),操作系统内核会分配接下来可以执行哪个任务,我们假设分配给了任务3执行。当任务3中断了,可能跳到了任务2,也可能跳回到了任务1,读取保存的执行信息,继续执行起来。
这里就会有3个线程之间的来回切换。
线程阻塞切换需要在操作系统的内核上面切换,会有用户态到内核态的切换。
协程与线程
上面描述我们知道,线程中任务的调度是由内核操作的,会有用户空间到内核空间的跨越,不利于系统性能。而聪明的程序员想到,何不自己写一套程序来控制任务之间的调度呢,这样将任务调度控制在用户空间。
关于协程,我们来看看维基百科上面关于协程的介绍:
协程非常类似于线程。但是协程是协作式多任务的,而线程典型是抢占式多任务的。这意味着协程提供并发性而非并行性。协程相比线程,优势是它们可以用于硬性实时的语境(在协程之间的切换不需要涉及任何系统调用或任何阻塞调用),这里不需要用来守卫关键区块的同步性原语(primitive)比如互斥锁、信号量等,并且不需要来自操作系统的支持。有可能以一种对调用代码透明的方式,使用抢占式调度的线程实现协程,但是会失去某些利益(特别是对硬性实时操作的适合性和相对廉价的相互之间切换)。
线程是协作式多任务的轻量级线程,本质上描述了同协程一样的概念。其区别,如果一定要说有的话,是协程是语言层级的构造,可看作一种形式的控制流,而线程是系统层级的构造,可看作恰巧没有并行运行的线程。这两个概念谁有优先权是争议性的:线程可看作为协程的一种实现,也可看作实现协程的基底。
一个线程其实就是执行一个子程序,那么什么什么是子程序呢?
子程序就是函数,在Java中就是方法。如果一个funA调用了funB,funB调用funC,那么,需要先执行完funC,再执行funB,最后再执行funA。
整个子程序内部调用是通过栈来实现的。
那么协程跟子程序有什么关系呢?
其实协程也是一个子程序,但是在执行子程序的过程中,子程序的内部可以中断,转而去执行别的子程序,之后又可以回来执行当前的子程序。
这个是不是有点像CPU的中断。
我们来看一段代码:
funA() { println("A1"); println("A2"); println("A3");}funB() { println("B1"); println("B2"); println("B3");}funC() { println("C1"); println("C2"); println("C3");}
如果上面的代码由协程执行,可能在执行funA的时候在内部某一点中断,然后就去执行funB,也有可能回去执行funC,最后的结果可能就是:
A1A2C1C3A3B3B2C2B1
在这里要注意的是3个函数之间是没有互相调用的。这里的显示也并没有使用多线程技术,而只是用了一个线程执行的。
既然多线程也能实现上面的功能,为什么还要诞生协程呢?
在协程中,子程序的切换不是线程间的切换,而是由程序本身去控制。所以相对于多线程,没有了线程之间来回切换的开销。特别是在线程数量很多的情况下。
如果在多线程中我们需要要操作共享资源,我们就需要使用锁,我们可能会使用各种不同级别的锁,甚至会使用操作系统层面的锁。如果是在协程中,就不需要使用锁了。
总的来说,协程提高了程序的执行的效率。如果我们的系统是多核的,我们可以利用多核加上协程最大程度地发挥系统性能。
有关协程的发展史
协程的概念最早在20世纪90年代就诞生了,而线程的概念是在80年代才提出的,就使用情况来说,协程的使用远远不如线程广泛。
近些年,一些编程语言的新贵Go和Kotlin纷纷引入了协程这个语言特性,使得协程这个似乎十分陌生的概念开始频繁进入大家的视野。
相信对于从事Java开发的程序员来说,没有听过协程也很正常,我也是在网上看到一篇腾讯的面试攻略,才知道有协程这个东西。
如果你掌握的语言是Go,Kotlin或者Python等语言,那就该了解下协程。大厂比较喜欢面试这些东西。
好了,如果别人问你什么是协程,你可以说:协程是一种轻量级线程。
参考
1.协程 - 维基百科,自由的百科全书 (wikipedia.org)-协程
2.多线程 - 维基百科,自由的百科全书 (wikipedia.org)-多线程
3.协程 - 廖雪峰的官方网站 (liaoxuefeng.com)-
标签: #python线程进程协程的区别 #线程和协程的关系 #python中协程和线程的区别 #python协程和多线程