+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2020-03(62)

2020-04(60)

2020-05(24)

2020-06(39)

2020-07(23)

Python之进程、线程及协程

发布于2020-03-27 10:04     阅读(395)     评论(0)     点赞(11)     收藏(2)


0

1

2

3

4

5

6

7

8

9


在这里插入图片描述

进程

在这里插入图片描述
在这里插入图片描述

进程的实现

import os
import time

def do_sth(name):
    """进程做的事情"""
    print("进程的名称:{} PID: {}".format(name, os.getpid()))
    time.sleep(10)
    print('进程要做的事情')

if __name__ =="__main__":
    p1 = Process(target=do_sth, args=('p1',))
    p2 = Process(target=do_sth, args=('p2',))
    # 启动进程
    p1.start()
    p2.start()
    p1.join()
    p2.join()

输出为:
进程的名称:p1 PID: 6700
进程的名称:p2 PID: 7364
进程要做的事情
进程要做的事情

进程之间的通信

使用Queue和Pipes实现进程之间 的通信,以下为Queue的使用案例。

import os
import time
from multiprocessing import Process, Queue

class WriteProcess(Process):

    # 要写的内容
    ls = [
        "第一行",
        "第二行",
        "第三行",
        "第四行"
    ]

    def __init__(self, q, *args, **kwargs):
        super().__init__()
        self.q = q

    def run(self):
        for line in self.ls:
            print("write: {}".format(line))
            self.q.put(line)
            time.sleep(1)


class ReadProcess(Process):
    def __init__(self, q, *args, **kwargs):
        super().__init__()
        self.q = q

    def run(self):
        while True:
            print(self.q.get())

if __name__ =="__main__":
	q = Queue()
    w = WriteProcess(q)
    r = ReadProcess(q)
    w.start()
    r.start()
    w.join()

    r.terminate() # 终止读操作进程,因为读操作进程执行死循环

输出为:
write: 第一行
第一行
write: 第二行
第二行
write: 第三行
第三行
write: 第四行
第四行

进程中的锁

在这里插入图片描述
Lock和RLock区别同线程类似。

不使用进程锁example

import time
from multiprocessing import Process, Lock


class WriteProcess(Process):
    """写入文件"""

    def __init__(self, file_name, num, lock, *args, **kwargs):
        self.file_name = file_name
        super().__init__(*args, **kwargs)
        self.num = num
        self.lock = lock

    def run(self):
        """写入文件业务逻辑"""
        try:
            # self.lock.acquire() # 关闭进程锁
            for i in range(5):
                with open(self.file_name, 'a+', encoding='utf-8') as f:
                    content = '现在是:{}:{}-{}\n'.format(self.name, self.pid, self.num)
                    f.write(content)
                    time.sleep(0.5)
                    print(content)
        finally:
            # self.lock.release()
            pass


if __name__ == "__main__":
    file_name = 'test.txt'
    lock = Lock()
    for x in range(5):
        p = WriteProcess(file_name, x, lock)
        p.start()

输出为:
现在是:WriteProcess-3:9308-2
现在是:WriteProcess-1:13764-0
现在是:WriteProcess-4:13380-3
现在是:WriteProcess-2:8180-1
现在是:WriteProcess-5:9564-4
现在是:WriteProcess-3:9308-2
现在是:WriteProcess-1:13764-0
现在是:WriteProcess-4:13380-3
现在是:WriteProcess-5:9564-4
现在是:WriteProcess-2:8180-1
现在是:WriteProcess-3:9308-2
现在是:WriteProcess-1:13764-0
现在是:WriteProcess-4:13380-3
现在是:WriteProcess-2:8180-1
现在是:WriteProcess-3:9308-2
现在是:WriteProcess-1:13764-0
现在是:WriteProcess-4:13380-3
现在是:WriteProcess-2:8180-1
现在是:WriteProcess-5:9564-4
现在是:WriteProcess-3:9308-2
现在是:WriteProcess-1:13764-0
现在是:WriteProcess-4:13380-3
现在是:WriteProcess-5:9564-4
现在是:WriteProcess-2:8180-1

使用进程锁example

import time
from multiprocessing import Process, Lock


class WriteProcess(Process):
    """写入文件"""

    def __init__(self, file_name, num, lock, *args, **kwargs):
        self.file_name = file_name
        super().__init__(*args, **kwargs)
        self.num = num
        self.lock = lock

    def run(self):
        """写入文件业务逻辑"""
        try:
            self.lock.acquire()
            for i in range(5):
                with open(self.file_name, 'a+', encoding='utf-8') as f:
                    content = '现在是:{}:{}-{}\n'.format(self.name, self.pid, self.num)
                    f.write(content)
                    time.sleep(0.5)
                    print(content)
        finally:
            self.lock.release()


if __name__ == "__main__":
    file_name = 'test.txt'
    lock = Lock()
    for x in range(5):
        p = WriteProcess(file_name, x, lock)
        p.start()

输出为:
现在是:WriteProcess-3:7876-2
现在是:WriteProcess-3:7876-2
现在是:WriteProcess-3:7876-2
现在是:WriteProcess-3:7876-2
现在是:WriteProcess-3:7876-2
现在是:WriteProcess-4:11456-3
现在是:WriteProcess-4:11456-3
现在是:WriteProcess-4:11456-3
现在是:WriteProcess-4:11456-3
现在是:WriteProcess-4:11456-3
现在是:WriteProcess-1:12440-0
现在是:WriteProcess-1:12440-0
现在是:WriteProcess-1:12440-0
现在是:WriteProcess-1:12440-0
现在是:WriteProcess-1:12440-0
现在是:WriteProcess-2:8596-1
现在是:WriteProcess-2:8596-1
现在是:WriteProcess-2:8596-1
现在是:WriteProcess-2:8596-1
现在是:WriteProcess-2:8596-1
现在是:WriteProcess-5:10656-4
现在是:WriteProcess-5:10656-4
现在是:WriteProcess-5:10656-4
现在是:WriteProcess-5:10656-4
现在是:WriteProcess-5:10656-4

进程池

import time
from multiprocessing import Pool, current_process

def run(file_name, num):
    with open(file_name, 'a+', encoding='utf-8') as f:
        now_process = current_process()
        # 写入的内容
        content = "{} - {} - {}\n".format(
            now_process.name,
            now_process.pid,
            num
        )
        print(content)
        f.write(content)
        time.sleep(1)

    return 'OK'

if __name__ == "__main__":
    pool = Pool(5)
    file_name = 'text_pool.txt'
    for i in range(10):
        # 同步执行
        rest = pool.apply(run, args = (file_name, i))
        # 异步执行
        # rest = pool.apply_async(run, args=(file_name, i))
        print("{1} - {0}".format(rest, i))

    pool .close()
    pool.join()

同步执行结果:
SpawnPoolWorker-2 - 13144 - 0

0 - OK
SpawnPoolWorker-4 - 10136 - 1

1 - OK
SpawnPoolWorker-1 - 13056 - 2

2 - OK
SpawnPoolWorker-3 - 12296 - 3

3 - OK
SpawnPoolWorker-5 - 13612 - 4

4 - OK
SpawnPoolWorker-2 - 13144 - 5

5 - OK
SpawnPoolWorker-4 - 10136 - 6

6 - OK
SpawnPoolWorker-1 - 13056 - 7

7 - OK
SpawnPoolWorker-3 - 12296 - 8

8 - OK
SpawnPoolWorker-5 - 13612 - 9

9 - OK

异步执行结果为:
0 - <multiprocessing.pool.ApplyResult object at 0x0023F6A0>
1 - <multiprocessing.pool.ApplyResult object at 0x00859850>
2 - <multiprocessing.pool.ApplyResult object at 0x00859958>
3 - <multiprocessing.pool.ApplyResult object at 0x008599E8>
4 - <multiprocessing.pool.ApplyResult object at 0x00859A78>
5 - <multiprocessing.pool.ApplyResult object at 0x00859B08>
6 - <multiprocessing.pool.ApplyResult object at 0x00859B98>
7 - <multiprocessing.pool.ApplyResult object at 0x00859C28>
8 - <multiprocessing.pool.ApplyResult object at 0x00859CB8>
9 - <multiprocessing.pool.ApplyResult object at 0x00859D48>
SpawnPoolWorker-2 - 11344 - 0

SpawnPoolWorker-4 - 7948 - 1

SpawnPoolWorker-3 - 10168 - 2

SpawnPoolWorker-1 - 4984 - 3

SpawnPoolWorker-5 - 5592 - 4

SpawnPoolWorker-2 - 11344 - 5

SpawnPoolWorker-4 - 7948 - 6

SpawnPoolWorker-3 - 10168 - 7

SpawnPoolWorker-1 - 4984 - 8

SpawnPoolWorker-5 - 5592 - 9

1、进程池同步执行任务:表示进程池中的进程在执行任务的时候一个执行完成另一个才能执行,如果没有执行完会等待上一个进程执行;
2、进程池异步执行任务:表示进程池中的进程同时执行任务,进程之间不会等待。
上述异步执行程序中如果将print("{1} - {0}".format(rest, i))改为print("{1} - {0}".format(rest.get(), i)),则异步执行效果与同步执行相同。

同步与异步的理解

1、函数或方法被调用的时候,调用者是否得到最终的结果。直接得到最终结果,就是同步调用。不直接得到的最终的结果,就是异步调用。

2、同步:就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回,一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用结果。如进程、线程同步,可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行;B依言执行,再将结果给A;A再继续操作

异步:调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说当一个异步功能调用发出后,调用者不能立刻得到结果。但是这个时候被调用者可以去执行下面的代码而不是一味的等待。

线程

在这里插入图片描述

并发及GIL(全局解释器锁)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
GIL的理解:

  1. GIL遵循的原则:“一个线程运行 Python ,而其他 N 个睡眠或者等待 I/O.”,GIL是CPython中特有的全局解释器锁,它主要锁定Python线程的CPU执行资源。
  2. 由于GIL的存在,导致python的多线程比单线程还慢,主要原因是在单核的时候,同时只有一个线程在执行CPU,所以这个线程总是能获取到GIL。而换到多核的时候,同时会有多个线程在不同的CPU核心上执行,此时不同线程之间就需要竞争GIL,而GIL只能同时被一个线程申请到,所以会导致其它线程处于闲置状态【即使它已经拥有了CPU资源】。所以Python在多核CPU上的多线程始终只有单线程在跑程序。
  3. GIL的存在,使得python在I/O密集型的应用更有优势,而在CPU密集型的应用上处于弱势。
  4. CPU密集型代码(各种循环处理、计数等等),在这种情况下,触发GIL的释放与再竞争(多个线程来回切换当然是需要消耗资源的),所以python下的多线程对CPU密集型代码并不友好。
  5. IO密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有IO操作会进行IO等待,造成不必要的时间浪费,而开启多线程能在线程A等待时,自动切换到线程B,可以不浪费CPU的资源,从而能提升程序执行效率)。所以python的多线程对IO密集型代码比较友好。

线程实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

单线程实现

import threading

def use_thread():
    """打印线程名称"""
    print("now threading name: {}".format(threading.current_thread().name))
    """使用线程实现"""
    t = threading.Thread(target = loop, name = "loop_thread")
    t.start()
    t.join()

if __name__ == "__main__":
    use_thread()

输出为:
now threading name: MainThread
now threading name: loop_thread
0
1
2
3
4

多线程的实现

import threading

class LoopThread(threading.Thread):
    """自定义线程类"""
    def run(self):
        n = 0
        while n < 5:
            print("now threading name: {}".format(threading.current_thread().name))
            print(n)
            time.sleep(1)
            n += 1

if __name__ == "__main__":
    t1 = LoopThread(name = 'use_thread_oop')
    t2 = LoopThread(name='use_thread_oop_2')
    t1.start()
    t2.start()
    t1.join()
    t2.join()

输出为:
now threading name: use_thread_oop
0
now threading name: use_thread_oop_2
0
now threading name: use_thread_oop_2
1
now threading name: use_thread_oop
1
now threading name: use_thread_oop_2
2
now threading name: use_thread_oop
2
now threading name: use_thread_oop_2
3
now threading name: use_thread_oop
3
now threading name: use_thread_oop_2
4
now threading name: use_thread_oop
4

import threading
import time

balance = 0

class BalanceThread(threading.Thread):

    def __init__(self, n):
        super().__init__()
        self.n = n

    def run(self):
        global balance
        print("original balance:{}   thread_name:{}".format(balance, self.name))
        # time.sleep(1)
        for i in range(5):
            try:
            # my_lock.acquire()
            # print(1)
            # my_lock.acquire()
            # print(2)
            balance = balance + self.n
            time.sleep(1)
            balance = balance - self.n
            time.sleep(1)
            print("{}>>>>>>>>: {}".format(self.name, balance))

if __name__ == "__main__":
    t1 = BalanceThread(5)
    t2 = BalanceThread(8)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

输出为:
在这里插入图片描述

多线程中锁的实现

在这里插入图片描述

Lock

import threading
import time

balance = 0
my_lock = threading.Lock()

class BalanceThread(threading.Thread):

    def __init__(self, n):
        super().__init__()
        self.n = n

    def run(self):
        global balance
        print("original balance:{}   thread_name:{}".format(balance, self.name))
        # time.sleep(1)
        for i in range(5):
            try:
                my_lock.acquire()
                print(1)
                # my_lock.acquire() LOCK命令如果加上此第二道锁,会产生死锁。资源已经被锁定,不能重复锁定
                # print(2)
                balance = balance + self.n
                time.sleep(1)
                balance = balance - self.n
                time.sleep(1)
                print("{}>>>>>>>>: {}".format(self.name, balance))
            finally:
                my_lock.release()
                # my_lock.release()

if __name__ == "__main__":
    t1 = BalanceThread(5)
    t2 = BalanceThread(8)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

输出为:
original balance:0 thread_name:Thread-1
1
original balance:5 thread_name:Thread-2
Thread-1>>>>>>>>: 0
1
Thread-1>>>>>>>>: 0
1
Thread-1>>>>>>>>: 0
1
Thread-1>>>>>>>>: 0
1
Thread-1>>>>>>>>: 0
1
Thread-2>>>>>>>>: 0
1
Thread-2>>>>>>>>: 0
1
Thread-2>>>>>>>>: 0
1
Thread-2>>>>>>>>: 0
1
Thread-2>>>>>>>>: 0
如果将第二道锁打开,输出为:
original balance:0 thread_name:Thread-1
1
original balance:0 thread_name:Thread-2
原因:资源已经被锁定,不能重复锁

RLock

import threading
import time

balance = 0
my_lock = threading.RLock()

class BalanceThread(threading.Thread):

    def __init__(self, n):
        super().__init__()
        self.n = n

    def run(self):
        global balance
        print("original balance:{}   thread_name:{}".format(balance, self.name))
        # time.sleep(1)
        for i in range(5):
            try:
                my_lock.acquire()
                print(1)
                my_lock.acquire()
                print(2)
                balance = balance + self.n
                time.sleep(1)
                balance = balance - self.n
                time.sleep(1)
                print("{}>>>>>>>>: {}".format(self.name, balance))
            finally:
                my_lock.release()
                my_lock.release()

if __name__ == "__main__":
    t1 = BalanceThread(5)
    t2 = BalanceThread(8)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

输出为:
original balance:0 thread_name:Thread-1
1
2
original balance:5 thread_name:Thread-2
Thread-1>>>>>>>>: 0
1
2
Thread-1>>>>>>>>: 0
1
2
Thread-1>>>>>>>>: 0
1
2
Thread-2>>>>>>>>: 0
1
2
Thread-2>>>>>>>>: 0
1
2
Thread-2>>>>>>>>: 0
1
2
Thread-2>>>>>>>>: 0
1
2
Thread-2>>>>>>>>: 0
1
2
Thread-1>>>>>>>>: 0
1
2
Thread-1>>>>>>>>: 0

Lock和RLock适用with语法

线程池

import threading
import time
from concurrent.futures.thread import ThreadPoolExecutor
from multiprocessing.dummy import Pool


def run(n):
    time.sleep(1)
    print(threading.current_thread().name, n)


def main():
    """不是用线程"""
    for n in range(5):
        run(n)


def main_use_thread():
    """适用线程"""
    ls = []
    for count in range(10):
        for i in range(10):
            t = threading.Thread(target=run, args=(i,))
            t.start()
            ls.append(t)

        for l in ls:
            l.join()


def main_use_pool():
    """使用线程池优化"""
    pool = Pool(10)
    pool.map(run, range(100))
    pool.close()
    pool.join()


def main_use_executor():
    """适用ThreadPoolExecutor类实现线程池"""
    with ThreadPoolExecutor(max_workers=10) as pool:
        pool.map(run, range(100))


if __name__ == "__main__":
    ts = time.time()
    main()
    print(time.time() - ts)

    ts = time.time()
    main_use_thread()
    print(time.time() - ts)

    ts = time.time()
    main_use_pool()
    print(time.time() - ts)

    ts = time.time()
    main_use_executor()
    print(time.time() - ts)

ThreadPoolExecutor比multiprocessing.dummy.Pool效率略高。

协程

在这里插入图片描述
在这里插入图片描述

yield实现

def yield_test():
    """实现协程函数"""
    while True:
        n = yield
        print(n)


if __name__ =="__main__":
    g = yield_test() # g是一个生成器
    next(g) # 程序运行到yield就停住了,等待下一个next
    # g.send(None) # 没有给x赋值,执行print语句,打印出None,继续循环停在yield处,等同于next()
    g.send(666) # 我们给yield发送值1,然后这个值被赋值给了x,并且打印出来,然后继续下一次循环停在yield处
    g.send(888) # 同上next(g)
    g.send(999) # 同上next(g)

输出为:
666
888
999
经典生产者消费者模型:

def consumer():
    r = ''
    while True:
        n = yield r
        if not n:
            print("return")
            return
        print('[CONSUMER] Consuming %s...' % n)
        r = '200 OK'

def produce(c):
    # c.send(None)
    next(c)
    n = 0
    while n < 2:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r)

    try:
        # c.send(0)
        c.send(False)
        # c.send(None)
    except StopIteration:
        c.close()
        print("close")

c = consumer()
produce(c)

输出为:
[PRODUCER] Producing 1…
[CONSUMER] Consuming 1…
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2…
[CONSUMER] Consuming 2…
[PRODUCER] Consumer return: 200 OK
return
close

async&await

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

协程实现

import asyncio

async def do_sth(x):
    """定义协程函数"""
    print('等待中:{0}'.format(x))
    await asyncio.sleep(x)
    
# 判断是否为协程函数
print(asyncio.iscoroutinefunction(do_sth))

coroutine1 = do_sth(5)
# 事件的循环队列
loop = asyncio.get_event_loop()
# 注册任务
task = loop.create_task(coroutine1)
print(task)
# 等待协程任务执行结束
loop.run_until_complete(task)
print(task)

输出为:
<Task pending name=‘Task-1’ coro=<do_sth() running at D:/python-project/process_thread/use_async.py:5>>
等待中:5
<Task finished name=‘Task-1’ coro=<do_sth() done, defined at D:/python-project/process_thread/use_async.py:5> result=None>

协程之间通信

嵌套调用

async def compute(x, y):
    print("computing x + y")
    await asyncio.sleep(1)
    return x + y


async  def get_num(x, y):
    rest = await compute(x, y)
    print(rest)

loop = asyncio.get_event_loop()
task = loop.create_task(get_num(1, 2))
loop.run_until_complete(task)
loop.close()

输出为:
computing x + y
3

使用队列实现通信

# 1. 定义一个队列
# 2. 让两个协程来进行通信
# 3. 让其中一个协程往队列中写入数据
# 4. 让另一个协程从队列中删除数据

import asyncio
import random


async def add(store, name):
    """
    写入数据到队列
    :param store: 队列的对象
    :return:
    """
    for i in range(5):
        # 往队列中添加数字
        num = '{0} - {1}'.format(name, i)
        await asyncio.sleep(random.randint(1, 5))
        await store.put(i)
        print('{2} add one ... {0}, size: {1}'.format(
            num, store.qsize(), name))


async def reduce(store):
    """
    从队列中删除数据
    :param store:
    :return:
    """
    for i in range(10):
        rest = await store.get()
        print(' reduce one.. {0}, size: {1}'.format(rest, store.qsize()))


if __name__ == '__main__':
    # 准备一个队列
    store = asyncio.Queue(maxsize=5)
    a1 = add(store, 'a1')
    a2 = add(store, 'a2')
    r1 = reduce(store)

    # 添加到事件队列
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.gather(a1, a2, r1))
    loop.close()

输出为:
a1 add one … a1 - 0, size: 1
a2 add one … a2 - 0, size: 2
reduce one… 0, size: 1
reduce one… 0, size: 0
a2 add one … a2 - 1, size: 1
reduce one… 1, size: 0
a1 add one … a1 - 1, size: 1
reduce one… 1, size: 0
a1 add one … a1 - 2, size: 1
reduce one… 2, size: 0
a2 add one … a2 - 2, size: 1
reduce one… 2, size: 0
a1 add one … a1 - 3, size: 1
reduce one… 3, size: 0
a2 add one … a2 - 3, size: 1
reduce one… 3, size: 0
a1 add one … a1 - 4, size: 1
reduce one… 4, size: 0
a2 add one … a2 - 4, size: 1
reduce one… 4, size: 0

Condition

import random
from queue import Queue

import asyncio


class Bread(object):
    """ 馒头类 """

    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.name


async def consumer(name, basket, lock):
    """
    消费者
    :param name  协程的名称
    :param basket  篮子,用于存放馒头
    :return:
    """
    while True:
        async with lock:
            # 如果没有馒头了,则自己休息,唤醒生产者进行生产
            if basket.empty():
                print('{0}@@@消费完了@@@'.format(name))
                # 唤醒他人
                lock.notify_all()
                # 休息
                await lock.wait()
            else:
                # 取出馒头
                bread = basket.get()
                print('>>{0} 消费馒头 {1}, size: {2}'.format(
                    name, bread, basket.qsize()
                ))
                await asyncio.sleep(random.randint(1, 5))


async def producer(name, basket, lock):
    """
    生产者
    :param name  协程的名称
    :param basket  篮子,用于存放馒头
    :return:
    """
    print('{0} 开始生产'.format(name))
    while True:
        async with lock:
            # 馒头生产满了,休息生产者,唤醒消费者进行消费
            if basket.full():
                print('{0} 生产满了'.format(name))
                # 唤醒他人
                lock.notify_all()
                # 自己休息
                await lock.wait()
            else:
                # 馒头的名字
                bread_name = '{0}_{1}'.format(name, basket.counter)
                bread = Bread(bread_name)
                # 将馒头放入篮子
                basket.put(bread)
                print('>>{0} 生产馒头 {1}, size: {2}'.format(name, bread_name, basket.qsize()))
                # 计数+ 1
                basket.counter += 1
                await asyncio.sleep(random.randint(1, 2))


class Basket(Queue):
    """ 自定义的仓库 """
    # 馒头生产的计数器
    counter = 0


def main():
    lock = asyncio.Condition()
    # 篮子,用于放馒头,协程通信使用
    basket = Basket(maxsize=5)
    p1 = producer('P1', basket, lock)
    p2 = producer('P2', basket, lock)
    p3 = producer('P3', basket, lock)
    c1 = consumer('C1', basket, lock)
    c2 = consumer('C2', basket, lock)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.gather(p1, p2, p3, c1, c2))
    loop.close()


if __name__ == '__main__':
    main()

输出为:

P1 开始生产
>>P1 生产馒头 P1_0, size: 1
P2 开始生产
P3 开始生产
>>P2 生产馒头 P2_1, size: 2
>>P3 生产馒头 P3_2, size: 3
>>C1 消费馒头 P1_0, size: 2
>>C2 消费馒头 P2_1, size: 1
>>P1 生产馒头 P1_3, size: 2
>>P2 生产馒头 P2_4, size: 3
>>P3 生产馒头 P3_5, size: 4
>>C1 消费馒头 P3_2, size: 3
>>C2 消费馒头 P1_3, size: 2
>>P1 生产馒头 P1_6, size: 3
>>P2 生产馒头 P2_7, size: 4
>>P3 生产馒头 P3_8, size: 5
>>C1 消费馒头 P2_4, size: 4
>>C2 消费馒头 P3_5, size: 3
>>P1 生产馒头 P1_9, size: 4
>>P2 生产馒头 P2_10, size: 5
P3 生产满了
>>C1 消费馒头 P1_6, size: 4
>>C2 消费馒头 P2_7, size: 3
>>P1 生产馒头 P1_11, size: 4
>>P2 生产馒头 P2_12, size: 5
>>C1 消费馒头 P3_8, size: 4
>>C2 消费馒头 P1_9, size: 3
>>P1 生产馒头 P1_13, size: 4

协程理解参考链接:
廖雪峰的官方网站
网名还没想好

原文链接:https://blog.csdn.net/u012777971/article/details/105022712

0

1

2

3

4

5

6

7

8



所属网站分类: 技术文章 > 博客

作者:9384vfnv

链接: https://www.pythonheidong.com/blog/article/286926/e674b9272207012f2499/

来源: python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

11 0
收藏该文
已收藏

评论内容:(最多支持255个字符)