zoukankan      html  css  js  c++  java
  • Pyton(八)2、进程、线程、协程 _ 复习归纳篇

    一、自己的问题

    1.为什么要有三个程,没有他们代码也可以执行呀!!

    2.三者的区别及各自的优缺点。

    3.三者的相关代码重新敲一遍。

    可以浏览下面网址,作者详细阐明了三者的作用及区别。

    http://blog.csdn.net/u012332571/article/details/53419216 

    三个程的原理就是切换着去做所有的任务(比喻如下):

      假设你每天晚上需要做语文、数学、英语、物理、化学这5科的作业,每项作业耗时1小时。

          如果你先花1小时做语文作业,做完了,再花1小时做数学作业,这样,一次全部做完,一共花5小时,这种方式称为单任务模型,或者批处理任务模型。

      假设你打算切换到多任务模型,可以先做1分钟语文,再切换到数学作业,做1分钟,再切换到英语,以此类推,只要切换速度足够快,这种方式就和单核CPU执行多任务是一样的了,以幼儿园小朋友的         眼光来看,你就正在同时写5科作业。

      但是,切换作业是有代价的,比如从语文切到数学,要先收拾桌子上的语文书本、钢笔(这叫保存现场),然后,打开数学课本、找出圆规直尺(这叫准备新环境),才能开始做数学作业。操作系统在切       换进程或者线程时也是一样的,它需要先保存当前执行的现场环境(CPU寄存器状态、内存页等),然后,把新任务的执行环境准备好(恢复上次的寄存器状态,切换内存页等),才能开始执行。这个切       换过程虽然很快,但是也需要耗费时间。如果有几千个任务同时进行,操作系统可能就主要忙着切换任务,根本没有多少时间去执行任务了,这种情况最常见的就是硬盘狂响,点窗口无反应,系统处于假       死状态。所以,多任务一旦多到一个限度,就会消耗掉系统所有的资源,结果效率急剧下降,所有任务都做不好。

    1.为什么要有三个程,没有他们代码也可以执行呀!!

    答: 三个程的存在就是为了让函数同时执行,假如没有它们,func()函数要10分钟才执行完,func2()...以此类推,那么所有的函数执行完毕需要非常多的时间,

      有了三个程,就可以让他们同时执行,大大缩短了时间。

    2.三者的不同及各自的优缺点。

     进程:数据之间不共享,每个进程都独占一份内存,最高效的工作方式是 进程数 == 计算机核数。

     线程:数据共享,适合IO密集型任务、cpu消耗少的任务,如web。

     协程(异步IO):数据共享,它就是一个线程,但是可以执行多个任务,没有切换的开销,不需要多线程的锁机制,也不存在变量冲突。

    3.三程的代码

    进程:

    t = multiprocessing.Process()

    t.start()

    需要注意,在windows下面需要进行name的判断

    import multiprocessing
    
    a = 0
    def f(b):
        global a
        a += b
        print(a)
    
    
    if __name__ == '__main__':
        for iter in range(3):
            t = multiprocessing.Process(target=f,args=(1,))
            t.start()
    
    """
    #输出结果
    1
    1
    1
    
    可以看出全局变量a的值并没有得到改变,说明他们之间的不存在共享
    """
    进程基本操作

    Manager的数据共享

    #调用Manager 可以把任务中的数据放在里面,且它们是共享的。
    
    from multiprocessing import Manager,Process
    import time
    def func(type,i):
        type.append(i)
    
    if __name__ == '__main__':
        obj = Manager()
        lis = obj.list()
        #dic = obj.dict()
        #tup = obj.tuple()
        for iter in range(3):
            t = Process(target=func,args=(lis,iter))
            t.start()
            #t.join()   #等待任务全部执行完成,因为进程也是并发的所以,只有进程完全结束后,你才可以调用它们的结果。
        time.sleep(1)   #睡眠也是一样,当睡眠长度要超过执行的长度才可以取值成功。
        print(lis)
    Manager的数据共享

    线程:

    t = threading.Thread()

    t.start()

    from threading import Thread
    A = 0
    def func(a):
        global A
        A = A + a
        print(A)
    
    for iter in range(5):
        t = Thread(target=func, args=(iter,))
        t.start()
    
    
    #从结果可以看出,线程之间的数据是共享的。
    """
    输出结果
    0
    1
    3
    6
    10
    """
    线程基本操作

    t.setDaemon()

    #setDaemon(True) 时终止任务。
    from threading import Thread
    import time
    def func(a):
        print("Hello",a)
        time.sleep(0.001)
        print("lazy boy",a)
    
    for iter in range(10):
        t = Thread(target=func,args=(iter,))
        t.setDaemon(True)  #True False 两个必须填写一个,False代表什么也不干,True 表示执行
        t.start()
    #从结果可以看出,setDaemon()t.qq.com 为True时,终止任务。
    """
    输出结果:
    Hello 0
    Hello 1
    Hello 2
    Hello 3
    Hello 4
    Hello 5
    Hello 6
    Hello 7
    Hello 8
    lazy boy 1
    lazy boy 0
    Hello 9
    """
    setDaemon终止任务

    t.join()

    from threading import Thread
    import time
    def func(a):
        print("Hello",a)
        time.sleep(1)
        print("lazy boy",a)
    
    for iter in range(10):
        t = Thread(target=func,args=(iter,))
        t.start()
        t.join()
        
    #函数一步一步的执行,让多线程毫无意义。
    """
    输出结果
    Hello 0
    lazy boy 0
    Hello 1
    lazy boy 1
    Hello 2
    lazy boy 2
    Hello 3
    lazy boy 3
    Hello 4
    lazy boy 4
    Hello 5
    lazy boy 5
    Hello 6
    lazy boy 6
    Hello 7
    lazy boy 7
    Hello 8
    lazy boy 8
    Hello 9
    lazy boy 9
    """
    join让线程无意义

    Evnet()

    #做用阻塞
    from threading import Thread,Event
    import time
    def func(event,a):
        print("Hello")
        event.wait() #阻塞任务。
        print(a)
    
    event_obj = Event()
    for iter in range(10):
        t = Thread(target=func, args=(event_obj,iter))
        t.start()
    
    
    inp = input(">>>")
    if inp == "1":
        event_obj.set()
    #从结果可以看出一旦下了命令,就开始执行被阻塞的任务。
    #event_obj.clear() 清除set
    """
    Hello
    Hello
    Hello
    Hello
    Hello
    Hello
    Hello
    Hello
    Hello
    Hello
    9
    1
    4
    2
    5
    7
    8
    3
    0
    6
    """
    Event 阻塞

    线程锁

    作用:假设列表A的所有元素就为0,当一个线程从前向后打印列表的所有元素,另外一个线程则从后向前修改列表的元素为1,那么输出的时候,列表的元素就会一部分为0,一部分为1,这就导致了数据的不一致。锁的出现解决了这个问题。

    #因为线程是并发的并且数据共享,如果多个线程同时对数据进行修改,就会产生脏数据,锁的出现就是为了,不让线程同时修改。
    import threading
    import time
    
    globals_num = 0
    
    lock = threading.RLock()
    
    
    def Func():
        #lock.acquire()  # 获得锁
        global globals_num
        globals_num += 1
        time.sleep(1)
        print(globals_num)
        #lock.release()  # 释放锁
    
    
    for i in range(10):
        t = threading.Thread(target=Func)
        t.start()
    Rloack

    queue 队列:

    往队列里面放东西,put 往队列里面取东西 get   当队列放满时,会一直处于等待状态,利用并发,当管有空位置时,又开始放,取东西 当队列为空时,也会一直等待。

    #队列就是好比一根管,可以往管里面放东先也可以取东西。
    import queue,threading
    q = queue.Queue(maxsize=3)  #为了0时队列长度无限,
    
    q.put("你好")     #put方法是往队列里面放东西
    q.put("xxx")      #全部存在管里面
    q.put("xxx")      #当put的东西超出管的长度是会等待。
    q.put("xxx")
    for i in range(3):     #利用循环取出来
        g = q.get()         #get <= put 不等待
        print(g)            #get > put 等待
    队列
  • 相关阅读:
    IoC之Ninject
    C#中的扩展方法
    Office 2016 Pro Plus Project 专业版 Visio 专业版 64 位vol版本方便KMS小马oem
    Microsoft Office 2016 简体中文 Vol 版镜像下载
    svn 被锁住 冲突 Can't revert without reverting children
    定时检查服务批处理,发现服务停止立即启动服务
    C++中关于[]静态数组和new分配的动态数组的区别分析
    IP地址与无符号整数值相互转换
    算法:整数与ip地址转换
    将字符串表示的IP地址转变为整形表示
  • 原文地址:https://www.cnblogs.com/learn-python-M/p/6897354.html
Copyright © 2011-2022 走看看