zoukankan      html  css  js  c++  java
  • 并发编程

    并发编程

    一,操作系统发展史

    输入输出设备>>>:IO操作即(input和output)

    • 手工操作穿孔卡片

    • 批处理(磁带)

    • 脱机批处理系统

    一步步的优化,其实都是在提高计算机CPU利用率的问题(问题在于时串行并且没有空间上的复用)

    多道技术

    1,空间上的复用

    多个程序共享一套计算机硬件

    2,时间上的复用性
    切换+保存状态

    1,当一个程序长时间遇到IO操作系统就是剥夺该程序的cpu的权限(提高了cpu的利用率并且不影响程序的执行效率)

    2,当一个程序长时间的占用cup操作系统也会剥夺该程序的cpu的执行权限(降低了程序的执行效率)

    进程理论

    1,程序就是托代码

    2,进程就是正在运行的程序

    同步异步:表示的是任务的提交方式

    同步:任务提交之后原地等待任务的执行并拿到返回结果才走,期间不做任何事情(程序层面的表现是卡住了

    异步:等任务计较以后不在原地等待而是继续执行下一行代码(结果是要的,但是是用过其他的方式获取

    阻塞非阻塞:表示的程序的运行状态

    阻塞:阻塞态

    非阻塞:就绪态 ,运行态

    强调:同步异步和阻塞非阻塞是两个概念 不能混为一谈!!!!

    二,创建进程的两种方式

    创建进程就是在内存中重新开辟一块内存空间将允许的产生的代码丢进去
    一个进程对应的内存就是一块独立的内存空间
    进程与进程之间数据是隔离的,无法直接交互,但是可以通过某些技术实现之间的交互

    创建进程两种系统内部所对应的内部原理

    1,windows

    在创建进程会将代码以模块的方式从上往下执行一遍

    windows创建进程一定要在if name == 'main':代码块内创建 否则报错

    2,linux

    在创建进程的时候是直接将代码完完整整的拷贝一份

     

    创建的第一种方式:

    from multiprocessing import Process
    import time
    def test (name):
    print("%s你干啥去啊"%name)
       time.sleep(2)
       print("%s他走了"%name)
    if __name__ == "__main__":
       p = Process(target=test,args=("jason",))#创建一个进程对象target所对应的就是子程序
       p.start()#告诉操作系统帮你创建了一个进程
      print("主")#主程序

    创建进程的第二中方式

    from multiprocessing  import Process
    import time
    class Myprocess(Process):#直接继承这个类
       def __init__(self,name):
           super().__init__()
           self.name = name
       def run(self):
           print("%s你好啊"%self.name)
           time.sleep(2)
           print("%s你干啥去"%self.name)
    if __name__ == "__main__":
       p = Myprocess("jason")
       p.start()
       print("主程序")
       

    三,join方法

    join方法就是让你的子进程先运行然后在运行你的主程序

     

    from multiprocessing import Process
    import time

    def test(name,i):
       print('%s is running'%name)
       time.sleep(i)
       print('%s is over'%name)
    if __name__ == '__main__':
       p_list = []
       p = Process(target=test,args=('egon',1))
       p1 = Process(target=test,args=('kevin',2))
       p2 = Process(target=test,args=('jason',3))
       start_time = time.time()
       p.start()  # 仅仅是告诉操作系统帮你创建一个进程 至于这个进程什么时候创 操作系统随机决定
       p1.start()
       p2.start()
       p2.join()
       p.join()
       p1.join()

       # 主进程代码等待子进程运行结束 才继续运行
       # p.join() # 主进程代码等待子进程运行结束
       print('主')
       print(time.time() - start_time)

    三,进程间数据是隔离的

    from multiprocesssing import Process
    import time
    money = 99
    def test():
       global money
       money = 9999999
    if __name__ =="__main__":
       p = Process(target = test)
       p.start()
       p.join()
       print(money)

    该代码运行下来的结果是99因为在子进程中的内存空间中 他只是修改了他的那个变量内部的值

    而在主程序中的那个内存空间中 还是那个99

    四,进程对象及其他方法

    1,获取进程的pid

    1,os.getpid()是获得当前进程的进程号。系统每开辟一个新进程就会为他分配一个进程号

    2,os.getppid()查看当前进程号的父类的当前进程号

    3,is_alive()查看判断子进程是否存活,如果在那么返回True不在返回False

    4,terminate,告诉操作系统让他帮你杀死你的子进程

    from multiprocessing import Process,current_process

    5,current_process,这个也是获取当前进程的进程号

    from multiprocessing import Process,current_process
    import os
    import time


    def test(name):
       # print('%s is running'%name,current_process().pid)
       print('%s is running'%name,'子进程%s'%os.getpid(),'父进程%s'%os.getppid())
       time.sleep(3)
       print('%s is over'%name)


    if __name__ == '__main__':
       p = Process(target=test,args=('egon',))
       p.start()
       p.terminate()  # 杀死当前进程 其实是告诉操作系统帮你杀死一个进程
       time.sleep(0.1)
       print(p.is_alive())  # 判断进程是否存活
       # print('主',current_process().pid)
       print('主',os.getpid(),'主主进程:%s'%os.getppid())

    五,守护进程

    关键字: daemon将该进程设置为守护进程这句话必须放在start语句的后面否则报错

    而且主进程结束子进程死亡,子进程随之死亡

    就和古代妃子为皇帝陪葬一样,皇帝死了妃子都要去陪葬就是这个道理

    from multiprocessing import Process
    import time

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


    if __name__ == '__main__':
       p = Process(target=test,args=('egon',))
       p.daemon = True  # 将该进程设置为守护进程   这一句话必须放在start语句之前 否则报错
       p.start()
       time.sleep(0.1)
       print('皇帝jason寿正终寝')

    六,互斥锁

    当多个进程操作处理一份数据的时候会造成数据错乱这时候就要加锁处理

    将并发改成串行

    虽然降低了效率但是提高了按数据的安全

    注意:

    1,锁不要轻易使用不然容易造成死锁的现象

    2,只要在处理数据的时候的那部分加上锁不要再全局枷锁

    锁必须在主进程中产生,交给子进程去使用

    关键字

    1,mutex = Lock()生成一把锁,在python中只要是要用到互斥锁 尽量把变量名启程这个,属于你这样写人家也能看懂

    1,mutex.acquire() 抢锁,

    2,mutex.release() 释放锁

    模拟一个有关抢票的软件

    from multiprocessing import Process,Lock
    import time
    import json

    # 查票
    def search(i):
       with open('data','r',encoding='utf-8') as f:
           data = f.read()
       t_d = json.loads(data)
       print('用户%s查询余票为:%s'%(i,t_d.get('ticket')))

    # 买票
    def buy(i):
       with open('data','r',encoding='utf-8') as f:
           data = f.read()
       t_d = json.loads(data)
       time.sleep(1)
       if t_d.get('ticket') > 0:
           # 票数减一
           t_d['ticket'] -= 1
           # 更新票数
           with open('data','w',encoding='utf-8') as f:
               json.dump(t_d,f)
           print('用户%s抢票成功'%i)
       else:
           print('没票了')
           
    def run(i,mutex):
       search(i)
       mutex.acquire()  # 抢锁 只要有人抢到了锁 其他人必须等待该人释放锁
       buy(i)
       mutex.release()  # 释放锁


    if __name__ == '__main__':
       mutex = Lock()  # 生成了一把锁
       for i in range(10):
           p = Process(target=run,args=(i,mutex))
           p.start()

     

  • 相关阅读:
    Java 8 并行流与串行流
    Java 8 新增的 Stream
    Java 8 新增的 Lambda 表达式
    《CSS揭秘》 |用户体验与结构布局
    《CSS揭秘》 |阴影
    《CSS揭秘》 |形状
    《CSS揭秘》 |前言
    《CSS揭秘》 |背景与边框
    《CSS揭秘》 |CSS编码技巧
    《CSS揭秘》 |检测属性与属性值
  • 原文地址:https://www.cnblogs.com/yangxinpython/p/11329400.html
Copyright © 2011-2022 走看看