并发编程之守护进程、互斥锁以及队列等相关内容-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())

 

原文地址:https://www.cnblogs.com/usherwang/p/13554390.html