进程与线程

1.终止进程的两种方式:

1.join()让主进程等待子进程和结束,并回收子进程资源,主进程再结束并回收资源。

2.主进程正常结束,子进程与主进程一并被回收资源。

from multiprocessing import Process
import time
def task():
   print('start...')
   time.sleep(2)
   print('end...')
if __name__ == '__main__':
   p = Process(target=task)
   p.start()
   p.join()  #不加join会先不等待子进程,主进程先回收
   print('主进程结束')

2.僵尸进程与孤儿进程:

僵尸进程:

在子进程结束后,主进程没有正常结束,子进程PID不会被回收。

缺点:

1.操作系统中的pid是有限的,如果子进程pid号无法正常回收,则会占用pid号

2.浪费资源

3.若pid号满了,则无法创建新的进程。

孤儿进程:

在子进程没有结束的时候主进程没有正常结束,子进程不会被会回收。

操作系统优化机制(孤儿院)

当主进程意外终止,操作系统会检测是否有正在运行的子进程,会将他们放入孤儿院中,让操纵系统帮你自动回收。

from multiprocessing import Process
from multiprocessing import current_process #查看进程id
import os
import time
def task():
   print(f'start...{current_process().pid}')
   time.sleep(5)
   print(f'end.....{os.getpid()}')
   print('子进程结束')
if __name__ == '__main__':
   p = Process(target=task)
   p.start()
   print(f'进入主进程的io--{current_process().pid}')
   time.sleep(2)
   print(f'进入主进程的IO--{os.getpid()}')
   print('主进程结束')
   print(f'查看主主进程{os.getpid()}')#同样常看进程id
   f = open('yy.txt')

3.守护进程

当主进程结束时,子进程也会被回收

from multiprocessing import Process
import time
def demo(name):
   print(f'start.....{name}')
   time.sleep(8)
   print(f'end....{name}')
   print('子进程结束啦啊啦啦啦啦啦啦')
if __name__ == '__main__':
   p = Process(target=demo,args=('童子鸡一号', ))
   p.daemon = True #将子进程p设为子进程
   p.start()
   time.sleep(9)#如果主进程运行时间比子进程块则主进程被回收时子进程也会被回收不会再执行
   print('这个王爷有点帅')

4.进程之间数据是隔离的

from multiprocessing import Process
import time
number = 10
def func():
   global number
   number = 100
   print(number)#100

# def func2(number):
#     number += 100
   # print(number)
if __name__ == '__main__':
   p = Process(target=func)
   # p1 = Process(target=func2, args=(number,))
   p.start()
   # p1.start()
   p.join()
   # p1.join()
   time.sleep(1)
   print(number)#10
   print(number)#10

5.互斥锁:

抢票栗子:
from multiprocessing import Process
from multiprocessing import Lock #进程互斥锁
import random
import time
import json
#查看余票
def search(name):
   #读取json文件中的数据
   with open('data.json','r',encoding='utf-8') as f:
       data_dic = json.load(f)
       print(f'用户{name}查看余票,余票还剩{data_dic.get("number")}')
#购买火车票如果购买成功就减少票数
def buy(name):
   with open('data.json','r',encoding='utf-8')as f:
       data_dic = json.load(f)
   #到这一步谁先谁得到票
   if data_dic.get('number') > 0:
       data_dic['number'] -= 1
       #模拟网络延迟
       time.sleep(random.randint(1,3))
       with open('data.json','w',encoding='utf-8') as f:
           json.dump(data_dic,f)
           print(f'用户{name},抢票成功')
   else:
       print(f'用户{name},抢票失败')
def run(name,lock):
   #假设多人购买票转成串行一个一个买
   search(name)
   lock.acquire()  #加锁
   buy(name)
   lock.release() #释放锁
if __name__ == '__main__':
   lock = Lock()
   #开启并发多进程,实习呢并发
   for line in range(7):
       obj = Process(target=run,args=(f'史迪仔{line}',lock))
       obj.start()

6.队列

相当于第三方管道。

from multiprocessing import Queue   #multiprocessing提供的队列,先进先出
from multiprocessing import JoinableQueue  # 基于 Queue 封装的队列 先进先出
import queue  # python内置的队列 先进先出
         #队列中没有了put_nowait会报错
q_obj = Queue(5)   #表示队列中只能存在五份数据
q_obj.put_nowait('json')
print('田间草木深1')
q_obj.put_nowait('1')
print('田间草木深2')
q_obj.put_nowait('2')
print('田间草木深3')
q_obj.put_nowait('3')
print('田间草木深4')
q_obj.put_nowait('4')
print('田间草木深5')
q_obj.put_nowait('5')
print('田间草木深6')
from multiprocessing import Queue   #multiprocessing提供的队列,先进先出
         #队列中没有了put不会报错进入阻塞状态
q_obj = Queue(6)
q_obj.put('json')
print('田间草木深1')
q_obj.put('1')
print('田间草木深2')
q_obj.put('2')
print('田间草木深3')
q_obj.put('3')
print('田间草木深4')
q_obj.put('4')
print('田间草木深5')
q_obj.put('5')
print('田间草木深6')

7.IPC机制(进程之间通信)

from multiprocessing import Process
from multiprocessing import JoinableQueue
import time
def stak(q):
   x = 100
   q.put(x) #将数据添加到对列中
   print('添加进程')
   time.sleep(3)
   print(q.get())   #取出队列中的数据现在是1234

def task2(q):
   res = q.get()    #取出队列中的数据现在是x的值100
   print(f'获取的数据时是{res}')
   q.put(1234) #将1234添加到数据队列q中

if __name__ == '__main__':
   q = JoinableQueue(5) #创建一个存放五份数据的队列
   p1 = Process(target=stak,args=(q,))
   p2 = Process(target=task2,args=(q,))
   p1.start()
   p2.start()
   总而言之言而总之就是队列中的数据可以被进程共享

8.生产者与消费者

生产者:生产数据的

消费者:使用数据的

from multiprocessing import JoinableQueue
from multiprocessing import Process
import time


def producer(name, food, q):
   msg = f'{name}生产了{food}'
   q.put(food)
   print(msg)


def customer(name, q):
   while True:
       try:
           time.sleep(1)
           food = q.get_nowait()
           msg = f'{name}吃了{food}'
           print(msg)
       except Exception:
           break


if __name__ == '__main__':
   q = JoinableQueue()
   #C=创建两个生产者
   for line in range(5):
       p = Process(target=producer, args=('tank', f'猪饲料{line}',q))
       p.start()
   #创建两个消费者
   c1 = Process(target=customer,args=('jason',q))
   c2 = Process(target=customer,args=('sean',q))
   c1.start()
   c2.start()

9.线程

进程:资源单位

线程:执行单位

线程与进程都是虚拟的概念,为了跟好的表达某种事物

开启一个进程一定自带一个线程,线程才是真正的执行者。

为什么使用线程:

节省资源的占用

开启进程:1)产生一个内存空间,申请一块资源。

2)自动产生一个主进程。

3)开启子进程的速度要比子线程慢很多。

开启线程: 1)一个进程里可以开启多个线程,从进程的内存空间中申请执行单位。

2)节省资源

IO密集型:多线程

io时间由用户定:阻塞:切换+保存状态

计算密集型:多进程

计算时间由操作系统定:计算时间很长:切换+保存状态

进程与进程之间数据是隔离的,线程与线程数据之间是共享的

from threading import Thread
import time
number = 1000

# #启动线程方式一
# def task():
#     global number
#     number = 100
#     print('start.....')
#     time.sleep(1)
#     print('end....')
#
# if __name__ == '__main__':
#     t = Thread(target=task
#     t.start()
#     print('主进程')
#     print(number)

#启动线程方式二
class Mythread(Thread):
   def run(self):
       print('start...')
       time.sleep(1)
       print('end...')
if __name__ == '__main__':
   t = Mythread()
   t.daemon = True
   t.start()
   print('主进程')
   
#查看子进程
class Mythread(Thread):
   def run(self):
       print(f'start...{current_thread().name}')
       time.sleep(1)
       print(f'end...{current_thread().name}')
if __name__ == '__main__':
   t = Mythread()
   t.daemon = True
   t.start()
   t.join()
   print('主进程')
   print(number)

10.线程锁与进程锁一样

from threading import Lock
from threading import Thread
import time
lock = Lock()

# 开启10个线程,对一个数据进行修改
number = 100


def task():
   global number

   lock.acquire()#加锁时修改数据按顺序变成串联一个一个修改
   number2 = number
   time.sleep(1)
   number = number2 - 1
   lock.release() #解锁


if __name__ == '__main__':

   list1 = []
   for line in range(10):
       t = Thread(target=task)
       t.start()
       list1.append(t)

   # for t in list1:
       t.join()
   print(number)  # 90
   print('主进程')

 

原文地址:https://www.cnblogs.com/cyfdtz/p/12018623.html