线程 、进程、协程的基本使用

进程(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的代码,从上到下执行.默认的正常情况代码
  • 异步非阻塞:效率是最高的,cpu过度充分,过度发热 液冷

事件 (Event)

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

Event_test.py:

from multiprocessing import Process, Event
import time, random
# (2) 模拟经典红绿灯效果
def traffic_light(e):
    print("红灯亮")
    while True:
        if e.is_set():   # 判断当前的属性是否为True  (默认上来是False)
            # 绿灯状态,亮1秒钟
            time.sleep(1)
            print("红灯亮")
            e.clear()	# 将这个属性的值改成False
        else:		
            # 红灯状态,亮1秒钟
            time.sleep(1)
            print("绿灯亮")	
            e.set()		# 将这个属性的值改成True	
e = Event()
traffic_light(e)

运行视图:
在这里插入图片描述

守护进程

守护进程守护的是主进程,如果主进程中的所有代码执行完毕了,
当前这个守护进程会被立刻杀死,立刻终止.
语法:
进程.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 : 互斥锁就是进程的互相排斥,谁先抢到资源,谁就上锁改资源内容,为了保证数据的同步性
# 注意:多个锁一起上,不开锁,会造成死锁.上锁和解锁是一对.

进程间通信 IPC

进程队列(Queue):

队列特点: 先进先出,后进后出
queue.py:

from multiprocessing import Process,Queue
import queue
"""队列特点: 先进先出,后进后出"""

q = Queue()
# 1.put 往队列中放值
q.put(100)
q.put(101)
q.put(102)
# 2.get 从队列中取值
res = q.get()
print(res)
res = q.get()
print(res)
# res = q.get()
# print(res)
# 3.队列中如果已经没有数据了,在调用get会发生阻塞.
res = q.get()
print(res)
# 4.get_nowait 存在系统兼容性问题[windows]好用 [linux]不好用 不推荐
res = q.get_nowait()
print(res)
# try:
# 	res = q.get_nowait()
# 	print(res)
# except queue.Empty:
# 	pass
# 5.设置队列的长度
"""设置队列长度最多存放4个元素"""
q = Queue(4)
# IPC Inter-Process Communication
# 实现进程之间通信的两种机制:
    # 管道 Pipe
    # 队列 Queue
    
# put() 存放
# get() 获取
# get_nowait() 拿不到报异常
# put_nowait() 非阻塞版本的put
q.empty()      检测是否为空  (了解)
q.full() 	   检测是否已经存满 (了解)

–线程(Thread)

生产者与消费者模型

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值