zoukankan      html  css  js  c++  java
  • 线程 、进程、协程的基本使用

    进程(Process)、线程(Thread)、协程(Coroutine)的概念:

    进程:
    就是正在运行的程序,它是操作系统中,资源分配的最小单位.,
    资源分配:分配的是cpu和内存等物理资源。
    进程号是进程的唯一标识。
    默认情况下一个进程只有一个线程,在进程里面可以创建多个线程。
    线程:
    cpu执行程序的最小单位, 通过线程去执行进程中代码, 线程是执行代码的分支,
    线程是依附在进程里面的, 没有进程就没有线程,
    同一个程序执行两次之后是两个进程
    进程和进程之间的关系: 数据彼此隔离,通过socket通信
    协程:
    协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
    协程在子程序内部可中断的,然后转而执行别的子程序,在适当的时候再返回来接着执行。

    并行和并发

    • 并发:一个cpu同一时间不停执行多个程序
    • 并行:多个cpu同一时间不停执行多个程序

    同步和异步

    • 同步是指代在程序执行多个任务时,按部就班的依次执行,必须上一个任务执行完有了结果以后,才会执行下一个任务。
    • 异步是指代在程序执行多个任务时,没有先后依序,可以同时执行,所以在执行上一个任务时不会等待结果,直接执行下一个任务。一般最终在下一个任务中通过状态的改变或者通知、回调的方式来获取上一个任务的执行结果。

    cpu的进程调度方法

    # 先来先服务fcfs(first come first server):先来的先执行
    # 短作业优先算法:分配的cpu多,先把短的算完
    # 时间片轮转算法:每一个任务就执行一个时间片的时间.然后就执行其他的.
    # 多级反馈队列算法
    
    越是时间长的,cpu分配的资源越少,优先级靠后
    越是时间短的,cpu分配的资源越多
    

    进程的性质:

    1. 进程之间的数据彼此隔离
    2. 多个进程之间是异步并发

    –进程(Process):

    进程的基本使用:

    import os, time, random
    from multiprocessing import Process
    def func(n):
        time.sleep(random.randrange(3))
        print("数字{}<=>1.子进程id>>{},2父进程id>>{}".format(n, os.getpid(), os.getppid()))
    	
    if __name__ == "__main__":
        for i in range(1, 11):
            # 创建子进程,返回进程对象,执行func这个任务
            p = Process(target=func, args=(i,))  # args=(i,)传递参数
            # 调用子进程
            p.start()  # 可简写成 Process(target=func, args=(i,)).start()
        print("主进程执行结束了....")
        print(os.getpid())  # os.getpid()进程号
    
    

    运行视图:
    在这里插入图片描述
    运行视图不唯一,因为多个进程之间是异步并发

    进程的join 函数:

    1. join 等待当前子进程全部执行完毕之后,主进程在执行(用来同步子父进程的)

    例:

    p = Process(target=func,args=(i,))
    p.join()
    

    同步 异步 / 阻塞 非阻塞

    • 同步:必须等我这件事干完了,你在干,只有一条主线,就是同步
    • 异步:没等我这件事情干完,你就在干了,有两条主线,就是异步
    • 阻塞:比如代码有了input,就是阻塞,必须要输入一个字符串,否则代码不往下执行
    • 非阻塞:没有任何等待,正常代码往下执行.
    • 同步阻塞 :效率低,cpu利用不充分
    • 异步阻塞 :比如socketserver,可以同时连接多个,但是彼此都有recv
    • 同步非阻塞:没有类似input的代码,从上到下执行.默认的正常情况代码

    事件 (Event)

    • 异步非阻塞:效率是最高的,cpu过度充分,过度发热 液冷

    事件 (Event)阻塞事件 :

    ‘’’
    e = Event()生成事件对象e
    e.wait()动态给程序加阻塞 , 程序当中是否加阻塞完全取决于该对象中的is_set() [默认返回值是False]
    # 如果是True 不加阻塞
    # 如果是False 加阻塞

    # 阻塞事件 :
    	e = Event()生成事件对象e   
    	e.wait()动态给程序加阻塞 , 程序当中是否加阻塞完全取决于该对象中的is_set() [默认返回值是False]
        # 如果是True  不加阻塞
        # 如果是False 加阻塞
    
    # 控制这个属性的值
        # set()方法     将这个属性的值改成True
        # clear()方法   将这个属性的值改成False
        # is_set()方法  判断当前的属性是否为True  (默认上来是False)
    

    Event_test.py:

    在这里插入代码片
    

    控制这个属性的值

    # set()方法     将这个属性的值改成True
    # clear()方法   将这个属性的值改成False
    # is_set()方法  判断当前的属性是否为True  (默认上来是False)
    
    在这里插入代码片
    
    场景在多任务当中
    同步:必须等我这件事干完了,你在干,只有一条主线,就是同步
    异步:没等我这件事情干完,你就在干了,有两条主线,就是异步
    阻塞:比如代码有了input,就是阻塞,必须要输入一个字符串,否则代码不往下执行
    非阻塞:没有任何等待,正常代码往下执行.
     
    # 同步阻塞  :效率低,cpu利用不充分
    # 异步阻塞  :比如socketserver,可以同时连接多个,但是彼此都有recv
    # 同步非阻塞:没有类似input的代码,从上到下执行.默认的正常情况代码
    # 异步非阻塞:效率是最高的,cpu过度充分,过度发热 液冷
    

    守护进程

    守护进程守护的是主进程,如果主进程中的所有代码执行完毕了,
    当前这个守护进程会被立刻杀死,立刻终止.
    语法:
    进程.daemon = True 设置当前这个进程为守护进程
    必须写在start()调用进程之前进行设置

    默认:主进程会默认等待所有子进程执行结束之后,在关闭程序,释放资源
    代码:

    from multiprocessing import Process
    import time
    # (3) 守护进程实际用途: 监控报活
    # 守护进行
    def alive():
    	while True:
    		print("给监控的总服务器发消息,报告自己的存活状态, i am alive~")
    		time.sleep(1)
    
    # 执行任务
    def func():
    	while True:
    		try:
    			time.sleep(1)
    			raise RuntimeError
    			print("当前5号服务器功能:对日志进行数据分析.... ")
    		except:
    			break
    			# pass
    
    if __name__ == "__main__":
    	# 创建2个子进程
    	p1 = Process(target=alive)
    	p2 = Process(target=func)
    	# 设置p1为守护进程
    	# p1.daemon = True
    	p1.start()
    	p2.start()
    	# 必须等到p2任务执行结束之后,在向下执行.
    	p2.join()
    	print("当前服务器状态异常 ... ")
    
    
    

    没有设置守护进程视图:
    在这里插入图片描述
    设置守护进程视图:
    在这里插入图片描述

    #可以给子进程贴上守护进程的名字,该进程会随着主进程代码执行完毕而结束(为主进程守护)
    (1)守护进程会在主进程代码执行结束后就终止
    (2)守护进程内无法再开启子进程,否则抛出异常(了解)
    

    锁(Lock)

    上锁和解锁是一对,只上锁不解锁会发生死锁现象(代码阻塞,不往下执行了)
    互斥锁 : 互斥锁是进程之间的互相排斥,谁先抢到这个锁资源就先使用,后抢到后使用
    信号量:Semaphore 本质上就是锁,只不过可以控制上锁的数量
    look:
    lock.acquire()# 上锁
    lock.release()# 解锁

    # 创建一把锁
    lock = Lock() 
    # 上锁
    lock.acquire()
    # 连续上锁不解锁是死锁
    # lock.acquire() error
    
    print("厕所中...")
    
    # 解锁
    lock.release()
    print("执行程序 ... ")
    

    Semaphore:

    from multiprocessing import Semaphore,Process
    import time,random
    sem = Semaphore(4)
    sem.acquire()
    # sem.acquire()
    # sem.acquire()
    # sem.acquire()
    # sem.acquire() # 上第五把锁出现死锁状态.
    print("执行响应的操作") 
    sem.release()
    """
    # 总结:
    Semaphore 可以设置上锁的数量
    同一时间最多允许几个进程上锁
    创建进程的时候,是异步并发
    执行任务的时候,遇到锁会变成同步程序.
    """
    
    lock.acquire()# 上锁
    lock.release()# 解锁
    #同一时间允许一个进程上一把锁 就是Lock
    	加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲速度却保证了数据安全。
    #同一时间允许多个进程上多把锁 就是[信号量Semaphore]
    	信号量是锁的变形: 实际实现是 计数器 + 锁,同时允许多个进程上锁	
    
    # 互斥锁Lock : 互斥锁就是进程的互相排斥,谁先抢到资源,谁就上锁改资源内容,为了保证数据的同步性
    # 注意:多个锁一起上,不开锁,会造成死锁.上锁和解锁是一对.
    

    事件(Event)

    # 阻塞事件 :
    	e = Event()生成事件对象e   
    	e.wait()动态给程序加阻塞 , 程序当中是否加阻塞完全取决于该对象中的is_set() [默认返回值是False]
        # 如果是True  不加阻塞
        # 如果是False 加阻塞
    
    # 控制这个属性的值
        # set()方法     将这个属性的值改成True
        # clear()方法   将这个属性的值改成False
        # is_set()方法  判断当前的属性是否为True  (默认上来是False)
    

    进程间通信 IPC

    # IPC Inter-Process Communication
    # 实现进程之间通信的两种机制:
        # 管道 Pipe
        # 队列 Queue
        
    # put() 存放
    # get() 获取
    # get_nowait() 拿不到报异常
    # put_nowait() 非阻塞版本的put
    q.empty()      检测是否为空  (了解)
    q.full() 	   检测是否已经存满 (了解)
    

    –线程(Thread)

    生产者与消费者模型

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LYUQwS07-1611230808561)(assets/生产者消费者.png)]

  • 相关阅读:
    【luogu T34117 打油门】 题解
    【luogu P1774 最接近神的人_NOI导刊2010提高(02)】 题解
    【luogu P1462 通往奥格瑞玛的道路】 题解
    【luogu P3808 AC自动机(简单版)】 模板
    替罪羊树~讲解
    【luogu P3369 【模板】普通平衡树(Treap/SBT)】 模板 Scapegoat Tree
    【luogu P1801 黑匣子_NOI导刊2010提高(06)】 题解
    【luogu P2590 [ZJOI2008]树的统计】 题解
    【luogu P3398 仓鼠找sugar】 题解
    【luogu P3884 [JLOI2009]二叉树问题】 题解
  • 原文地址:https://www.cnblogs.com/cndeveloper/p/14310940.html
Copyright © 2011-2022 走看看