python-进程调度_进程对象及方法_互斥锁_队列_IPC

进程

1. 进程调度

1. 先来先服务

2. 短作业优先

3. 时间片轮转

4. 多级反馈队列

2. 僵尸进程 孤儿进程

1. 僵尸进程: 进程结束了,资源还没来得及回收

2. 孤儿进程: 主进程退出,子进程还没有结束,他就会被专门的进程接管

3. 进程对象及其他方法

# 1. windows : tasklist | findstr PID
# 2. mac linux : ps aux | grep PID
# 3. 进程对象: t = Process(target=task)
#    进程内部: current_process()
# 4. t.pid 或者 current_process().pid  => 获取进程 id 号
# 5. os.getpid() 获取进程 id 号
# 6. os.getppid() 获取父进程 id 号
# 7. t.is_alive()或current_process().is_alive() 查看进程是否存活
# 8. t.terminate() 关闭进程,在主进程关闭

# 案例
import os
import time
from multiprocessing import Process
from multiprocessing import current_process

# 每个进程都会有自己的 id号: pid
def task():
    print('子进程')
    
    # 当前进程的 id 号
    print(current_process().pid)
    print(os.getpid()) # 跟上面打印出来是一模一样的
    
    # 取出该进程的父 id 号
    print(os.getppid())
    
    # current_process() 当前进程对象
    
    print(current_process().is_alive())
    time.sleep(2)
    
    print('子进程结束')
    
if __name__ == "__main__":
    t = Process(target=task)
    t.start()
    t1 = Process(target=task)
    t1.start()
    t.is_alive() 
    print('主进程打印结果',t.is_alive())
    print(t.pid)
    time.sleep(0.5)
    t.terminate() # 把 t 进程关闭
    print('主进程打印结果',t.is_alive)

4. 守护进程

import os
import time
from multiprocessing import Process
from multiprocessing import current_process

def task():
    # print(os.getpid())
    print('子进程')
    time.sleep(100)
    print('子进程结束')
    
if __name__ == "__main__":
    t = Process(target=task)
    # 守护进程: 主进程一旦结束,子进程也随之结束
    t.daemon = True # 一定要加在启动之前
    t.start()
    
    time.sleep(1)
    print('主进程结束')
    print('os.getppid()')
    time.sleep(100)

5. 互斥锁

# 同时只有一个人能拿到,必须释放,其他人才能再次获取到

import json
import time
import random
from multiprocessing import Process
from multiprocessing import Lock

def search():
    # 查看票数
    # 打开文件 读出 ticket_count
    with open('ticket','r',encoding='utf-8') as f:
        dic = json.load(f)
        print('余票还有: ',dic.get('ticket_count'))
        
def buy():
    with open('ticket','r',encoding='utf-8') as f:
        dic = json.load(f)
        
    time.sleep(random.randint(1,3)) # 模拟网络延迟
    if dic.get('ticket_count') > 0:
        # 能够买票
        dic['ticket_count'] -= 1
        # 保存到文件中
        with open('ticket','w',encoding='utf-8') as f:
            json.dump(dic,f)
            print('买票成功')
    else:
        # 买票失败
        print('买票失败')
        
# 写一个函数 先查票 再买票
def task(mutex):
    search()
    # 买票过程要加锁
    # 买前加锁
    mutex.acquire()
    buy()   # 10个进程变成了串行执行
    # 买后释放锁
    mutex.release()
    with mutex:
        buy()
        
if __name__ == "__main__":
    # 锁的创建: 主进程创建锁
    mutex = Lock() # 创建一把锁
    # 模拟十个人买票(开10个进程)
    for i in range(10):
        t = Process(target=task,args=(mutex,))
        t.start()
# ### 锁 lock
from multiprocessing import Process,Lock
# (1) lock基本用法
"""
上锁和解锁是一对,只上锁不解锁会发生死锁现象(代码阻塞,不往下执行了)
互斥锁 : 互斥锁是进程之间的互相排斥,谁先抢到这个锁资源就先使用,后抢到后使用
"""

"""
# 创建一把锁
lock = Lock()
# 上锁
lock.acquire()
# 连续上锁不解锁是死锁
# lock.acquire() error

print("厕所中...")

# 解锁
lock.release()
print("执行程序 ... ")
"""

# (2) 模拟12306抢票软件
import json,time

# 读写数据库中的票数
def wr_info(sign,dic=None):
	if sign == "r":
		with open("ticket",mode="r",encoding="utf-8") as fp:
			dic = json.load(fp)
		return dic
		
	elif sign == "w":
		with open("ticket",mode="w",encoding="utf-8") as fp:
			json.dump(dic,fp)
		
# res = wr_info("r")
# print(res)
# dic = {"count":0}
# wr_info("w",dic)

# 抢票方法
def get_ticket(person):
	# 获取数据库中实际的票数
	dic = wr_info("r")
	print(dic)
	
	# 模拟一下网络延迟
	time.sleep(0.5)
	
	# 判断票数
	if dic["count"] > 0 :	
		print("%s抢到票了" % (person))
		dic["count"] -= 1
		wr_info("w",dic)
	else:
		print("%s没有抢到这张票" % (person))

def run(person,lock):
	
	# 查看剩余票数
	dic = wr_info("r")	
	print("%s 查询票数: %s" % (person , dic["count"]) )	
	
	# 上锁
	lock.acquire()
	# 开始抢票
	get_ticket(person)
	lock.release()

if __name__ == "__main__":
	lock = Lock()
	lst = ["李志辉","宋云杰","高云峰","戈隆","孙致和","李虎玲","袁伟倬","刘鑫炜","马生平","刘鑫"]
	for i in lst:
		p = Process(target=run,args=(i,lock))
		p.start()

"""
创建进程的时候,仍然是异步并发,
在执行到上锁时,多个进程之间变成了同步程序.
先来的先上锁,先执行,后来的进程后上锁,后执行
"""

6. 面向对象高级

# 面向对象高级: 魔法方法 (__开头的) , __enter__ 和 __exit__,
# with 上下文管理器
# 自己写一个类,实现类似于打开文件 with open 的功能
'''
with MyClass('文件名','方式','编码') as f:
	f.read()
	
顶格写代码,f就关闭了	
'''

class MyClass():
    def __init__(self,file_name,mode,encoding):
        self.file_name = file_name
        self.mode = mode
        self.encoding = encoding
        
    def __enter__(self):
        print('只要有with,就会执行我')
        self.file = open(self.file_name,self.mode,encoding=self.encoding)
        
        return self.file
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        # 只要顶格写代码,就会执行我
        print('只要顶格写代码,就会执行我')
        self.file.close()

with MyClass('ticket','r','utf-8') as f:
    print(f.read())
    print('xxss')
    print('safdas')
 
a = MyClass('ticket','r','utf-8')

7. 队列介绍

from multiprocessing import Queue

# 实例化得到一个对象
q = Queue(5) # 默认很大,可以放很多,括号写5就是只能放5个

# 往管道中放值
q.put(1)
q.put('lqz')
q.put(18)
q.put(19)
q.put(20)
q.put(21)
q.put_nowait(100)

# 从管道中取值
print(q.get())
print(q.get())
print(q.get())
print(q.get(timeout=0.1))  # 等0.1s还没有值,就结束
print(q.get_nowait())      # 不等,有就是有,没有就没有

print(q.empty())  # 看一下队列是不是空的
print(q.full())   # 看一下队列是不是满的

# 总结
'''
q = Queue(队列大小)

# 放值
q.put(abcd)
q.put_nowait(abcd)  # 队列满了,放不进去就不放,报错

# 取值
q.get()             # 从队列头部取出一个值
q.get_nowait()      # 从队列头部取值,没有就报错

# 队列是否为空,是否满
print(q.empty())    # 看一下队列是不是空的
print(q.full())     # 看一下队列是不是满的
'''
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个元素"""

print("<======>")
q2 = Queue(4)
q2.put(200)
q2.put(201)
q2.put(202)
# q2.put(203)
# 如果超过了队列的指定长度,在继续存值会出现阻塞现象
# q2.put(204)

# 6.put_nowait() 非阻塞版本的put,超出长度后,直接报错
q2.put_nowait(204)
try:
	q2.put_nowait(205)
except queue.Full:
	pass

# ### 2.进程之间的数据共享
def func(q3):
	# 2.子进程获取数据
	res = q3.get()
	print(res)
	
	# 3.子进程存数据
	q3.put("马生平")

if __name__ == "__main__":
	q3 = Queue()
	p = Process(target=func,args=(q3,))
	p.start()
	
	# 1.主进程添加数据
	q3.put("王凡")
	
	# 为了等待子进程把数据放到队列中,需要加join
	p.join()
	
	# 4.主进程获取数据
	res = q3.get()
	print(res)
	
	print("主程序结束 ... ")

8. 进程间通信 IPC

IPC : Inter-Process Communication

import os
import time
from multiprocessing import Process
from multiprocessing import current_process
from multiprocessing import Queue

def task1(q):
    print('我是task1进程,我的id号是: %s' %os.getpid())
    q.put('lqz is handsome')
    
def task2(q):
    res = q.get()
    print('我是task2进程,我的id号是: %s' %os.getpid(),res)
    print('我是task2进程,我的id号是: %s' %os.getpid())
    
if __name__ == '__main__':
    q = Queue(5)
    
    t1 = Process(target=task1,args=(q,))
    t1.start()
    t2 = Process(target=task2,args=(q,))
    t2.start()
    
    print(q.get())

9. Manager 进程间共享数据

# Manager ( list 列表 , dict 字典) 进程之间的共享数据(列表或者字典等)

from multiprocessing import Process,Manager,Lock

def work(data,lock):

	# 1.正常写法
	# 上锁
	lock.acquire()
	# 修改数据
	data["count"] -= 1
	# 解锁
	lock.release()
	
	# 2.使用with语法可以简化上锁和解锁两步操作
	with lock:
		data[0] += 1

if __name__ == "__main__":
	lst = []
	lock = Lock()
	m = Manager()
	data = m.dict( {"count":20000} )
	data = m.list( [1,2,3] )
	for i in range(50):
		p = Process(target=work,args=(data,lock))
		p.start()
		lst.append(p)
		
	# 确保所有进程执行完毕之后,在向下执行,打印数据,否则报错.
	for i in lst:
		i.join()
		
	print(data)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

I believe I can fly~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值