python的伪线程与排他锁 /day19

python中的线程竟然是伪线程,确实这是毋庸置疑的,这是作为一名程序员的我今天才知道的,为什么会这样呢?

原因在于刚开始python语言的开发时候,电脑用的是单核CPU,而python语言的设计者设计了一个GIL,用它来作为一个排它锁,以便完成计算机的任务。

随着CPU核数的增多,python开发人员也意识到这个问题,当时python开发的原班人马也想修改GIL,但是最后还是放弃了,因为GIL作为python开发的源头机制牵扯的东西太多,修改难度太高。他们修改的是python语言解释器。那么什么是python语言解释器,以及python文件是怎么运行的呢?

废话不说,上图:

python语言解释器,就是把程序员能看懂的语言(简单来说是相对高级的语言)转换成电脑能看懂的语言(机器语言),相当于一个翻译官,把人说的话翻译给鸟听翻译给鱼听等等。

那么问题来了,计算机语言包括哪些呢?

哈哈,上图吧!

简单来说是这样,深入的话百度比我解释的要详细。

因此python语言产生了一个缺点-----速度慢效率差,这可能是当时python语言解释器是基于单核CPU的机制所引起的。但是python也具有自己明显的优点,因为拥有大量的三方库,所以开发简单高效。

为了解决这个问题python的开发人员又研究出一种新的机制---协程,协程这个东西貌似是python独有的(读书少不敢太确定),协程这个东西比线程要小,所以又叫微线程,微线程是比线程更小的调度单位。

协程有两种实现方式:(1)通过yield实现    (2)通过greentlet实现

第一种方式的实现代码如下:

import time
from greenlet import greenlet
def consumer(name):
    while True:
        baozi=yield              #yield有返回和中断的能力
        print("%s--吃了包子%d"%(name,baozi))
        time.sleep(1)
def producer():
    # r=c1.__next__()
    # r=c2.__next__()
    c1.__next__()
    c2.__next__()
    n=1
    while True:
        print("厨师一下生产两个包子------生产了包子%d"%(n))
        c1.send(n)
        c2.send(n+1)
        n+=2
if __name__ == '__main__':
    c1=consumer("c1")
    c2=consumer("c2")
    p=producer()

第二种实现方式:

from greenlet import greenlet
def test1():
    print("10")
    # 切换gr2中执行
    gr2.switch()
    print("12")
    # 切换gr2中执行
    gr2.switch()

def test2():
    print("11")
    # 切换gr1中执行
    gr1.switch()
    print("13")
#把要执行的代码放入greenlet()中
gr1=greenlet(test1)
gr2=greenlet(test2)
#切换gr1中执行
gr1.switch()

方式二的结果为 10,11,12,13

在这里说明一下:协程是一个单独的执行单元,自带CPU上下文,什么意思呢,简单来说就是可以记忆自己上次执行的状态,以及下下次应该执行什么代码。比如下图:

在斐波那契函数中每次运行next(),就会出来一个值,就是因为他记忆了自己上次运行的状态,要不然就会丢失数据了。

更简明来说yield就是分割上下文的地方。

猜你喜欢

转载自blog.csdn.net/qq_39112101/article/details/88560891