day35,锁机制

                                                                                         锁机制     

守护进程

    什么是守护进程:

     守护进程也是一个普通的进程,

     守护进程就是一个进程守护另一个进程,皇帝身边的侍卫一样

结论就是:a 是 b的守护进程,那么如果b进程结束了那么这个a进程就会随着一起挂掉

使用场景有: 在qq中下载一个文件时,立马退出qq后,这样的情况就是使用守护进程,因为qq退出后文件也应该下载,这个就像当与是守护进程

案例:

from multiprocessing import Process
import time

# 妃子的一生
def task():
    print("入宫了.....")
    time.sleep(50)
    print("妃子病逝了......")

if __name__ == '__main__':
    # 康熙登基了
    print("登基了.....")

    # 找了一个妃子
    p = Process(target=task)

    # 设置为守护进程 必须在开启前就设置好
    p.daemon = True
    p.start()

    # 康熙驾崩了
    time.sleep(3)
    print("故事结束了!")

互斥锁

     什么是互斥锁:锁其实就是一个状态,通过这个状态来执行代码的先后顺序,如果这个状态为True其他的进程就不能使用,

     为什么需要互斥锁:因为在我们多着进程操作一起操作同一个文件的时候,会出现一个进程在读另一个进程在写,这种情况,像这种情况有很多

     锁和进程中的join区别:

         join 也可以解决上面的这个情况,但是有一个问题,使用join的话就会把多个进程同时操作同一个文件,转换为串行,这样还不如不创建多个进程,

         互斥锁可以解决上面的问题也可以保证多个进程同时运行.相比join互斥锁在这方面更好些

案例:

day35,锁机制
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()

def task3(lock):
    lock.acquire()
    print("hello iam jason")
    time.sleep(random.randint(0,2))
    print("gender is women")
    time.sleep(random.randint(0,2))
    print("age is  26")
    lock.release()

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

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

    p1.start()
    # p1.join()

    p2.start()
    # p2.join()

    p3.start()
    # p3.join()

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

# if my_lock == False:
#     my_lock = True
#      #被锁住的代码
      my_lock = False 解锁
View Code

注意1: 不要对同一把执行多出acquire 会锁死导致程序无法执行 一次acquire必须对应一次release

 注意2:想要保住数据安全,必须保住所有进程使用同一把锁

IPC

    IPC指的是两个进程之间的通讯

    因为在内存中进程和进程之间是相互分离的

实现两个进程之间的通讯的方式有四种

    1, 管道实现:但是管道只能单向传输二进制数据

    2,文件传输:在硬盘上创建共享文件,缺点:传输速度慢,优点:数据的大小几乎没有限制

    3,socket 实现 : 缺点:实现过程比较复杂

    4,共享内存:必须由操作系统来分配 优点:传输速度快 缺点:数据量不能太大

使用共享内存实现两个进程的通信:

    使用通过两个类实现

     Manager :它提供了很多的数据的结构,list dict 等等

     Manager创建出来的数据结构是具有进程间共享的特性

    案例:

    

rom 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创建的数据的结构有一个缺点:创建的这个数据结构是没有锁机制的,所以这个不常用,因为需要自己手动的添加锁机制

Queue 实现两个进程的通信

   Queue是一个队列是一种特殊的数据结构,先存储的先取出 就像排队 先进先出 

   相反的是堆栈,先存储的后取出, 就像衣柜 桶装薯片 先进后出

   Queue 的优点是,

      1,它创建个数据结构是拥有锁机制的,不需要手动的添加锁,

      2, 储存和获取都是有顺序的

      3,储存的的个数是不限量的 

   扩展:

   函数嵌套调用时 执行顺序是先进后出 也称之为函数栈

   调用 函数时 函数入栈 函数结束就出栈

案例:

day35,锁机制
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有效
View Code

生产者和消费者模式

是什么

模型 就是解决某个问题套路

产生数据的一方称之为生产者

处理数据的一方称之为消费者

例如: 爬虫 生活中到处都是这种模型

饭店 厨师就是生产者 你吃饭的人就是消费者

生产者和消费者出啥问题了? 解决什么问题

生产者和消费,处理速度不平衡,一方快一方慢,导致一方需要等待另一方

生产者消费者模型解决这个问题的思路: 怎么解决

原本,双方是耦合 在一起,消费必须等待生产者生成完毕在开始处理, 反过来

如果消费消费速度太慢,生产者必须等待其处理完毕才能开始生成下一个数据

解决的方案:

将双方分开来.一专门负责生成,一方专门负责处理

这样一来数据就不能直接交互了 双方需要一个共同的容器

生产者完成后放入容器,消费者从容器中取出数据

这样就解决了双发能力不平衡的问题,做的快的一方可以继续做,不需要等待另一方

案例:

def eat(q):
    for i in range(10):
        # 要消费
        rose = q.get()
        time.sleep(random.randint(0, 2))
        print(rose,"吃完了!")

# 生产任务
def make_rose(q):
    for i in range(10):
        # 再生产
        time.sleep(random.randint(0, 2))
        print("第%s盘青椒肉丝制作完成!" % i)
        rose = "第%s盘青椒肉丝" % i
        # 将生成完成的数据放入队列中
        q.put(rose)

if __name__ == '__main__':
    # 创建一个共享队列
    q = Queue()
    make_p = Process(target=make_rose,args=(q,))
    eat_p =  Process(target=eat,args=(q,))


    make_p.start()
    eat_p.start()
上一篇:Python9-进程理论-day35


下一篇:寒假Day35:HTML表格+图像+超链接