zoukankan      html  css  js  c++  java
  • 并发编程之守护进程、互斥锁以及队列等相关内容-37

    1.回顾

    ···创建进程的两种方式

    ····第一种
    from multiprocessing import Process
    import time


    def task(n):
       print('我是子进程')
       time.sleep(n)
       print('子进程结束')


    if __name__ == '__main__':
       # args=(), kwargs={}
       # t=Process(task,args=(1,))
       t = Process(target=task, kwargs={'n': 1})
       t.start()  # 通知操作系统,开启进程,执行task函数
       print('主')

    ····第二种:
    from multiprocessing import Process
    import time

    class Task(Process):
       def __init__(self, n):
           super().__init__()
           self.n = n

       def run(self):
           print('我是子进程')
           time.sleep(self.n)
           print('子进程结束')


    if __name__ == '__main__':
       t = Task(1)
       # t.run(1) # 不是调用t.run(),而是调用t.start()
       t.start()
       print('主')


    ···join的使用
    from multiprocessing import Process
    import time


    def task(n):
       print('我是子进程')
       time.sleep(n)
       print('子进程结束')


    if __name__ == '__main__':
       ctime = time.time()
       t = Process(target=task, kwargs={'n': 1})
       t2 = Process(target=task, kwargs={'n': 2})
       t.start()
       t2.start()
       t.join()  # 等待t子进程执行完成
       t2.join()  # 等待t2子进程执行完成
       print('主')
       ctime2 = time.time()
       print(ctime2 - ctime)


    ···进程之间数据隔离
    from multiprocessing import Process
    import time

    age = 18


    def task(n):
       global age  # 局部修改全局
       age = 99
       print('我是子进程')
       time.sleep(n)
       print('子进程结束')
       print(age)


    if __name__ == '__main__':
       t = Process(target=task, kwargs={'n': 1})
       t.start()
       t.join()  # 等待t子进程执行完成
       print('主')
       print(age) # 数据没有变,主进程中打印age和子进程的age没有半毛钱关系,数据是隔离的

    2.进程的其他方法

    from multiprocessing import Process,current_process
    import time
    import os

    # 每个进程都会有自己的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() # t这个进程是否存活
       # print('主进程打印的结果',t.is_alive())
       print(t.pid)
       time.sleep(0.5)
       # t.terminate() # 把t进程关闭
       # time.sleep(0.1)
       print('主进程打印的结果', t.is_alive())

    3.守护进程

    from multiprocessing import Process, current_process
    import time
    import os


    def task():
       # print(os.getpid())
       print('子进程')
       time.sleep(200)
       print('子进程结束')


    if __name__ == '__main__':
       t = Process(target=task, )
       # 守护进程:主进程一旦结束,子进程也结束
       # t.daemon=True # 一定要加在启动之前
       t.start()

       time.sleep(1)
       print('主进程结束')
       print(os.getppid())
       time.sleep(100)

    #守护进程是随着主进程的代码结束而结束的,注意只是代码跑完,守护进程就结束
    # 问题1 :主进程的父进程是谁?就是pycharm
    # 问题2 :主进程开了很多子进程,每个都需要设置守护吗?看你的需求,你想让某个进程是守护:t.daemon=True

    4.互斥锁

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


    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()

    # 面向对象高级:魔法方法(__开头的),__enter__和__exit__,上下文管理器
    # 自己写一个类,实现类似于打开文件 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("sdfadasf")
    #
    #
    # # a=MyClass('ticket','r','utf-8')
    #

    5.队列



    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=100)) # 等0.1s还没有值,就结束
    # print(q.get_nowait())       # 不等了,有就是有,没有就没有

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


    # 总结:
    '''
    q=Queue(队列大小)
    # 放值
    q.put(asdf)
    q.put_nowait(asdf) # 队列满了,放不进去就不放了,报错

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


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

    6.进程间通信--IPC机制

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


    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())

     

  • 相关阅读:
    [每日一讲] Python系列:浅拷贝与深拷贝
    [每日一讲] Python系列:变量、内存管理与传递
    [每日一讲] Python系列:字典
    [每日一讲] Python系列:列表与元组
    [已开源/文章教程]独立开发 一个社交 APP 的源码/架构分享 (已上架)
    从选择到上传,可能是最贴心的高仿朋友圈编辑了
    完整的社交app源码android+laravel
    基于Laravel+Swoole开发智能家居后端
    APP架子迁移指南(三)
    Laravel如何优雅的使用Swoole
  • 原文地址:https://www.cnblogs.com/usherwang/p/13554390.html
Copyright © 2011-2022 走看看