码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2021-01-22 12:17:22      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:and   上下   empty   数据   socket   多级   release   情况   结果   

进程(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)]

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

标签:and   上下   empty   数据   socket   多级   release   情况   结果   

原文地址:https://www.cnblogs.com/cndeveloper/p/14310940.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!