线程理论-生产者消费模型-IPC机制-进程间通信-互斥锁-僵尸进程与孤儿进程

昨日内容回顾

如何复习知识点:总分总

先列出提纲,再依次复习,最后再总结一下

  • 操作系统的发展史
    """其实主要就是围绕cpu的利用率问题"""
    
  • 多道技术
"""单核实现并发的效果

并发:看起来像同时运行的可以叫做并发
并行:真正意义上的同时运行

ps:明星出轨>>>:星轨

空间与时间上的复用
	空间上:多个程序公用一套计算机硬件
	时间上:切换+保存状态
"""
# 切换分为两种
# 1.当一个程序遇到io操作,操作系统会立刻剥夺该程序的cpu执行权限(提供了cpu利用率并且不影响程序的执行效率)
# 2.当一个程序长时间占用cpu,操作系统也会立刻剥夺该程序的cpu执行权限(降低了程序的运行效率但是玩出了并发的效果)
  • 进程

"""
程序就是一堆死代码 	 死
进程则是正在执行的过程 活
"""
# 进程的调度算法
"""
先来先服务调度算法
短作业优先调度算法
时间轮转法+多级反馈队列
"""
  • 进程运行的三状态图
"""
就绪态:一切程序必须要先过就绪态才能加入运行态
运行态:正在被cpu执行
阻塞态:程序遇到io操作了
理想:我们希望开发的程序一直处于就绪态与运行态之间
"""
  • 两对重要概念

    • 同步与异步
    """任务的提交方式"""
    同步:
    	任务提交之后原地等待任务的返回结果期间不做任何事情
    异步:
    	任务提交之后不原地等待任务的返回结果执行直接执行下一行代码结果由异步回调机制做处理
    
    • 阻塞非阻塞
    """程序的运行状态"""
    阻塞:阻塞态
    非阻塞:就绪态,运行态
    

    上面的两对概念通常会组合出现,但是最常用的就是异步非阻塞

  • 开启进程的两种方式

"""
from mutiprocessing import Peocess

# 1.类实例化产生对象
# 2.类的继承 run方法

在Windows里面开启进程的代码一定要写在main代码块内
创建一个进程就是在内存空间中申请一块内存空间将需要的代码丢进去
"""
  • join方法

"""
主进程等待子进程代码运行完毕后再往下执行代码
"""
  • 进程间数据是相互隔离的(默认情况下)

ps:人工智能相关参考网站

http://www.turingapi.com/

https://www.xfyun.cn/

https://ai.baidu.com/

作为一名python程序员当你遇到一个功能的时候,第一时间可以考虑是否有对应的模块已经帮你实现了该功能

pycharm经常过期,可以下载最新版本的pycharm,然后加入https://idea.medeming.com/此网站的激活码

进程对象及其他方法

"""
一台计算机上面运行着很多进程,那么计算机是如何区分并管理这些进程服务端的呢?
计算机会给每一个运行的进程分配一个PID号
如何查看 
	Windows电脑 
		进入cmd输入tasklist即可查看
		tasklist|findstr PID查看具体的过程
	mak电脑 
	进入终端之后输入ps aux
	ps aux|grep PID查看具体的进程
"""
from multiprocessing import Process, current_process
current_proces().pid  # 查看当前进程的进程号

import os
os.getpid()  # 查看当前进程的进程号
os.getppid()  # 查看当前进程的父进程的进程号

p.terminate()  # 杀死当前进程
# 是告诉操作系统帮你去杀死当前进程 但是需要一定的时间 而代码的运行速度极快
time.sleep(0.1)
print(p.is_alive())  # 判断当前进程是否存活

僵尸进程与孤儿进程

# 僵尸进程
"""
死了但没有死透
当你开设了子进程之后 该进程死后不会立刻释放占用的进程号
因为我要让父进程能够查看到它开设的子进程的一些基本信息 占用的pid号 运行时间等...
所有的进程都会步入僵尸进程
	父进程不死并且在无限制的创建子进程并且子进程也不结束
	回收子进程占用的pid号
		父进程等待子进程运行结束
		父进程调用join方法
"""
# 孤儿进程
"""
子进程存活,父进程意外死亡
操作系统会开设"儿童福利院"专门管理孤儿进程回收相关资源
"""

守护进程

from multiprocessing import Process
import time


def task(name):
    print('%s总管正在活着' % name)
    time.sleep(3)
    print('%s总管正在死亡' % name)


if __name__ == '__main__':
    # p = Process(target=task, args=('egon',))
    p = Process(target=task, args={'name':'egon'}, )
    p.daemon = True  # 将进程p设置成守护进程 一定要放在start方法上面才会有效否则会直接报错
    p.start()
    print('皇帝jason寿终正寝')

互斥锁

多个进程操作同一份数据的时候,会出现数据错乱的问题

针对上述问题,解决方式就是加锁处理:将并发变成串行,牺牲效率但是保证了数据的安全

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


# 查票
def search(i):
    # 文件操作读取票数
    with open('data', 'r', encoding='utf-8') as f:
        dic = json.load(f)
    print('用户%s查询余额:%s' % (i, dic.get('ticket_num')))
    # 字典取值不要用[]的形式,推荐使用get 代码避免报错


# 买票 1.先查 2.再买
def buy(i):
    # 先查票
    with open('data', 'r', encoding='utf-8') as f:
        dic = json.load(f)
    # 模拟网络延迟
    time.sleep(random.randint(1, 3))
    # 判断当前是否有票
    if dic.get('ticket_num') > 0:
        # 修改数据库 买票
        dic['ticket_num'] -= 1
        # 写入数据库
        with open('data', 'w', encoding='utf-8') as f:
            json.dump(dic, f)
        print('用户%s买票成功' % i)
    else:
        print('用户%s买票失败' % i)


# 整合上面两个函数
def run(i, mutex):
    search(i)
    # 给买票环节加锁处理
    # 抢锁
    mutex.acquire()
    buy(i)
    # 释放锁
    mutex.release()


if __name__ == '__main__':
    # 在主进程中生成一把锁 让所有的子进程抢 谁先抢到谁先买票
    mutex = Lock()
    for i in range(1, 10):
        p = Process(target=run, args=(i, mutex))
        p.start()
"""
扩展 行锁 表锁

注意:
	1.锁不要轻易的使用,容易造成死锁现象(我们写代码一般不会用到都是内部封装好的)
	2.锁只在处理数据的部分加来保证数据安全(只在争抢数据的环节加锁处理即可)
"""

进程间通信

队列Queue模块
"""
管道:subporcess 
	stdin sydout stderr
队列=管道+锁

队列:先进先出
堆栈:先进后出

from multiprocessing import Queue

# 创建一个队列
q = Queue(5)  # 括号内可以传数字 标示生成的队列最大可以同时存放的数据量
# 往队列中存数据
q.put(111)
q.put(222)
q.put(333)
print(q.full())  # 判断当前队列是否满了
print(q.empty())  # 判断当前队列是否空了
q.put(444)
q.put(555)

print(q.put(666))  # 当队列数据放满了之后 如果还有数据要放程序会阻塞 直到有位置让出来 不会报错
"""
存取数据 存是为了更好的取
千方百计地存,简单快捷的取

同在一个屋檐下
差距为何那么大
"""
# 去队列中取数据
v1 = q.get()
v2 = q.get()
v3 = q.get()
v4 = q.get()
v5 = q.get()
print(q.empty())
v6 = q.get_nowait()  # 没有数据直接报错queue.Empty
c6 = q.get(timeout=3)  # 没有数据之后原地等待三秒之后再报错 queue.Empty
try:
    v6 = q.get(timeout=3)
    print(v6)
    
except Exception as e:
    print('一滴都没有了!')
v6 = q.get()  # 队列中如果已经没有数据的话 get方法会原地阻塞
print(v1, v2, v3, v4, v5, v6)

"""
q.full()
q.empty()
q.get_nowait()
在多进程的情况下会不精确
"""
"""

IPC机制

from multiprocessing import Queue, Process

"""
研究思路
    1.主进程跟子进程借助于队列通信
    2.子进程跟子进程借助于队列通信
"""


def producer(q):
    q.put('我是23号技术 很高兴为您服务!')


def consumer(q):
    print(q.get())


if __name__ == '__main__':
    q = Queue()
    p = Process(target=producer, args=(q,))
    p1 = Process(target=consumer, args=(q,))
    p.start()
    p1.start()

生产者消费模型

"""
生产者:生产/制造东西的
消费者:消费/处理东西的
还模型除了上述两个之外还需要一个媒介
	生活中的例子:
		做包子的做完以后放在蒸笼(媒介)里面,买包子的去蒸笼里面拿
		生产者和消费者之间不是直接做交互的,而是借助于媒介做交互
生产者(做包子的) + 消费队列(蒸笼) + 消费者(吃包子的)
"""

线程理论

  • 什么是线程

     ~~~python
     """
     进程:资源单位
     线程:执行单位
     
     将操作系统比喻成一个大的工厂
     那么进程就相当于工厂里面的车间
     而线程就是车间里面的流水线
     
     每一个进程肯定自带一个线程
     
     再次总结:
     	进程:资源单位(起一个进程仅仅只是在内存空间中开辟一块独立的空间)
     	线程:执行单位(真正被CPU执行的其实是进程里面的线程,线程指的就是代码的执行过程,执行代码中所需要使用到的资源都找所在的进程索要)
     进程和线程都是虚拟单位,只是为了我们更加方便的描述问题
     """
     ~~~
    
  • 为何要有线程

"""
开设进程
	1.申请内存空间  耗资源
	2."拷贝代码"   耗资源
开线程
	一个进程内可以开设多个线程,在用一个进程内开设多个线程无需再次申请内存空间操作
	
总结:
	开设线程的开销要远远的小于进程的开销
	同一个进程下的多个线程数据是共享的!
    
"""
"""
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值