初学python之路-day35

1.守护进程

 1 守护进程:
 2 进程是一个正在运行的程序
 3 守护进程就是一个普通的进程,守护进程可以守护另一个进程
 4 
 5 
 6 如果b是a的守护进程,a是被守护的进程,a要是挂了,b也就随之结束了 
 7 
 8 
 9 from multiprocessing import Process
10 import time
11 
12 # 妃子的一生
13 def task():
14     print("入宫了.....")
15     time.sleep(50)
16     print("妃子病逝了......")
17 
18 
19 if __name__ == '__main__':
20     # 康熙登基了
21     print("登基了.....")
22 
23     # 找了一个妃子
24     p = Process(target=task)
25 
26     # 设置为守护进程 必须在开启前就设置好
27     p.daemon = True
28     p.start()
29 
30     # 康熙驾崩了
31     time.sleep(3)
32     print("故事结束了!")
View Code
使用场景:
父进程交给了子进程一个任务,任务还没有完成父进程就结束了,子进程就没有继续执行
的意义了 例如:qq 接收到一个视频文件,于是开启了一个子进程来下载,如果中途退出了qq,
下载任务就没必须要继续运行了

2.互斥锁

互斥锁:互相排斥的锁
作用:如果这个资源已经被锁了,其他进程就无法使用了
强调:互斥锁并不是真的把资源锁起来了,只是在代码层面限制你的代码不能执行

由于并发将带来资源的竞争问题:
当多个进程同时要操作同一个资源时,将会导致数据错乱的问题
所以有两个解决方法:
1.加join 
2.上互斥锁

加join的弊端:
1.原本并发变成了串行,虽然可以避免数据错乱问题,但是效率降低了,这样就没必要
开子进程了
2.原本多个进程之间是公平竞争,加join时,执行的顺序就定死了,这是不合理的 锁和join的区别: 1.join是固定了执行顺序,会造成父进程等待子进程;锁依然是公平竞争谁先抢到谁先
执行,父进程可以做其他事情
2.join是把进程的任务全部串行;锁可以锁任意代码 一行也可以 可以自己调整粒度
粒度:粒度越大意味着锁住的代码越多   效率越低
   粒度越小意味着锁住的代码越少   效率越高

from multiprocessing import Process,Lock
import time,random

def task1(lock):
    # 要开始使用了 上锁
    lock.acquire()       #就等同于一个if判断
    print("hello iam jerry")
    time.sleep(random.randint(0, 2))
    print("gender is boy")
    time.sleep(random.randint(0, 2))
    print("age is  15")
    # 用完了就解锁
    lock.release()

def task2(lock):
    lock.acquire()
    print("hello iam owen")
    time.sleep(random.randint(0,2))
    print("gender is girl")
    time.sleep(random.randint(0,2))
    print("age is  48")
    lock.release()


if __name__ == '__main__':
    lock = Lock()

    p1 = Process(target=task1,args=(lock,))
    p2 = Process(target=task2,args=(lock,))
  

    p1.start()
    # p1.join()

    p2.start()
    # p2.join()

    # print("故事结束!")
    
# 锁的伪代码实现 

# if my_lock == False:
#     my_lock = True
#      #被锁住的代码
      my_lock = False 解锁
 1 import json,os,time,random
 2 from multiprocessing import Process,Lock
 3 
 4 def show_ticket():
 5     with   open("json",'r',encoding="utf-8")as f:
 6         data=json.load(f)
 7     time.sleep(random.randint(0,2))
 8     print("%s正在查询 剩余票数:%s"%(os.getpid(),data["count"]))
 9 
10 def buy():
11     with open("json",'r',encoding="utf-8")as f:
12         data = json.load(f)
13         if data["count"]>0:
14             data["count"]-=1
15 
16             with  open("json",'w',encoding="utf-8")as f1:
17                 json.dump(data,f1)
18                 print("%s 恭喜你抢票成功 剩余票数:%s!" % (os.getpid(),data["count"]))
19         else:
20             print("%s抢票失败! " % os.getpid())
21 
22 def task(lock):
23     show_ticket()
24     lock.acquire()
25     buy()
26     lock.release()
27 
28 if __name__ == '__main__':
29     lock=Lock()
30     for i in range(1,11):
31         p=Process(target=task,args=(lock,))
32         p.start()
33 
34 json文件里:
35 {"count": 3}
抢票
注意:
1:  不要对同一把锁,执行多个acquire 会锁死导致程序无法执行;  一次acquire必
须对应一次release l
= Lock() l.acquire() print("抢到了!") # l.release() l.acquire() print("抢到了!") 2:想要保住数据安全,必须保住所有进程使用同一把锁

3.IPC

IPC:
Inter-Process Communication,进程间通信
通讯指的就是交换数据,由于进程之间内存是相互隔离的,当一个进程想要把数据给另外
一个进程,就需要考虑IPC 进程间通讯方式:
1.管道:只能单向通讯,数据都是二进制 2.文件:在硬盘上创建共享文件 优点:数据量几乎没有限制 缺点:速度慢 3.socket:编程复杂度较高 4.共享内存:必须由操作系统来分配 优点: 速度快 缺点: 数据量不能太大
共享内存的方式:
1.Manager类:提供很多数据结构  list dict等等
    Manager所创建出来的数据结构,具备进程间共享的特点

from multiprocessing import Process,Manager,Lock
import time


def task(data,l):
    l.acquire()
    num = data["num"] #
    time.sleep(0.1)
    data["num"] = num - 1
    l.release()

if __name__ == '__main__':
    # 让Manager开启一个共享的字典
    m = Manager()
    data = m.dict({"num":10})

    l = Lock()

    for i in range(10):
        p = Process(target=task,args=(data,l))
        p.start()

    time.sleep(2)
    print(data)

强调:Manager创建的一些数据结构是不带锁的 可能会出现问题
2.Queue队列:处理了锁的问题
队列是一种特殊的数据结构,先存储的先取出    就像排队    先进先出

相反的是堆栈,先存储的后取出, 就像衣柜 桶装薯片    先进后出
函数嵌套调用时  执行顺序是先进后出     也称之为函数栈  ,调用 函数时  函数入
栈 函数结束就出栈
from multiprocessing import Queue # 创建队列 不指定maxsize 则没有数量限制 q = Queue(3) # 存储元素 # q.put("abc") # q.put("hhh") # q.put("kkk") # print(q.get()) # q.put("ooo") # 如果容量已经满了,在调用put时将进入阻塞状态 直到有人从队
列中拿走数据有空位置 才会继续执行
#取出元素 # print(q.get())# 如果队列已经空了,在调用get时将进入阻塞状态 直到有人从存
储了新的数据到队列中 才会继续
# print(q.get()) # print(q.get()) #block 表示是否阻塞 默认是阻塞的 # 当设置为False 并且队列为空时 抛出异常 q.get(block=True,timeout=2) # block 表示是否阻塞 默认是阻塞的 # 当设置为False 并且队列满了时 抛出异常 # q.put("123",block=False,) # timeout 表示阻塞的超时时间 ,超过时间还是没有值或还是没位置则抛出异常 仅在
block为True有效

4.生产者消费者模型

生产者消费者模型
生产者:产生数据的一方
消费者:处理数据的一方
模型:解决某个问题套路

应用:
如:生产者和消费,处理速度不平衡,一方快一方慢,导致一方需要等待另一方   具体表
现为: 原本双方是耦合 在一起,消费必须等待生产者生成完毕在开始处理;反过来,如果消费
消费速度太慢,生产者必须等待其处理完毕才能开始生成下一个数据 模型提供的解决方案: 将双方分开来,一专门负责生成,一方专门负责处理;生产者完成后放入容器,消费者从
容器中取出数据,这样就解决了双发能力不平衡的问题,做的快的一方可以继续做,不需
要等待另一方
 1 from multiprocessing import Process,Queue
 2 import time,random
 3 
 4 def eat(q):
 5     for i in range(10):
 6         rose=q.get()
 7         time.sleep(random.randint(0,2))
 8         print(rose,"chiwanle~~~~~~~~~~")
 9 
10 
11 def cook(q):
12     for i in  range(10):
13         time.sleep(random.randint(0,2))
14         print("第%s盘青椒肉丝制作完成!"%(i+1))
15         rose="第%s盘青椒肉丝" % (i+1)
16         q.put(rose)
17 
18 
19 if __name__ == '__main__':
20     q=Queue()
21     cook_p=Process(target=cook,args=(q,))
22     eat_p=Process(target=eat,args=(q,))
23     cook_p.start()
24     eat_p.start()
生产者消费者模型

 

转载于:https://www.cnblogs.com/wangwei5979/p/10969689.html

你可能感兴趣的:(python,json,数据结构与算法)