• Process 进程之间的数据隔离问题,守护进程,锁,信号量,事件


    Process

    1.进程之间的数据隔离问题

    2.守护进程

    几个进程的模型 ---- 进程同步的工具

      有先后顺序,就是同步

      进程之间就是异步

      希望原本异步的多进程操作,维持一个顺序---同步工具

    1.锁 Lock

    2.信号量 Semaphore

    3.事件  Event

    from mulitprocessing import Process

    n = 100

    def func():

      global n

      n = n-1

      return  6666

    if __name__ == "__main__":

      nl = []

      for i in range(100):

        p = Process(target=func)

        p.start()

        nl.append(p)

      for p in nl:

        p.join()

      print(n)

    通过上面的代码我们知道进程与进程之间的数据是隔离的 , 内存空间是不能共享的 , 所以要想进行通信 , 必须借助其他手段,且这两个进程都是自愿的.

    子进程的执行结果父进程获取不到 , 如果父进程依赖子进程的执行结果呢?父进程如何获取子进程的执行结果?

    父子进程之间通过socket通信

    import time

    from multiprocessing import Process

    例一:

    def  func():

      print("begin")

      time.sleep(3)

      print("wahaha")

    if __name__ =="__main__":

      p = Process(target=func)

      p.daemon = True   #守护进程的属性,默认是False,如果设置成True,就表示设置这个子进程为一个守护进程 , 设置守护进程的操作应该在开启子进程之前,如果在开启之后会报错,不过代码一样会运行.

      p.start()

      time.sleep(1)

      print("主进程")

    例二:

    def func1():

      print("begin")

      time.sleep(3)

      print("wahaha")

    def func2():

      while True:

        print("in func2")

        time.sleep(0.5)

    if __name__ =="__main__":

      Process(target=func1).start()

      p = Process(target=func2)

      p.daemon = True

      p.start()

      time.sleep(1)

      print("主进程")

    设置成守护进程之后会有什么效果?

    守护进程会在主进程的代码执行完毕之后直接结束,无论守护进程是否执行完毕

    应用:

    报活 : 主进程还活着

    假如有100台机器,每台机器上有100个进程,总共10000个进程,守护进程如何向检测机制报活??为什么要用守护进程来报活呢?为什么不用主进程来工作呢?

    因为守护进程报活几乎不占用CPU,也不需要操作系统去调度;且主进程有自己的任务,不能严格的按时就会发送一条报活信息

    5.所有的进程的基本使用:

    进程:同一时刻可以做多件事情互相之间不影响

    socket  tcp server  采用多进程的知识点来解决原生socket同一时刻只能和一个client通信的弊端

    以下是代码的实现:

    服务器:

    import scoket

    from multiprocessing import Process

    def talk(conn):

      try:

        while 1:

          conn.send(b"hello")

          print(conn.recv(1024)

      finally:

        conn.close()

    if __name__ == "__main__":

      sk = socket.socket()

      sk.bind(("127.0.0.1",9090))

      sk.listen()

      try:

        while 1:

          conn,addr = sk.accept()

          Process(target=talk,args=(conn,)).start()

      finally:

        sk.close()

    客户端:

    import socket,os

    sk = socket.socket()

    sk.conn(("127.0.0.1",9090))

    while 1:

      print(sk.recv(1024)

      sk.send(b"world")

    sk.close()

    6.锁

    from multiprocessing import Lock,Process

    lock = Lock()  #创造了一把锁

    lock.acquire()  #获取了这把锁的钥匙

    lock.release()  #归还这把锁的钥匙

    加锁就是谁先拿到钥匙谁先进.

    我们通过一个例子来了解一下:

    抢票的例子,每个人都能查看余票,买票

    import json,time

    from multiprocessing import Lock,Process

    def search(i):

      with open("db")as f:count_dic = json.load(f)

      time.sleep(0.2)

      print("person %s 余票:%s张"%(i,count_dic["count"])

    def buy(i):

      with open("db")as f:count_dic = json.load(f)

      time.sleep(0.2)

      if count_dic[''count''] > 0:

        count_dic[''count''] -= 1

        print("person %s购票成功"%i)

      time.sleep(0.2)

      with open("db","w")as f: json.dump(count_dic,f)

    def task(i,lock):

      search(i)

      lock.acquire()

      buy(i)

      lock.release()

    if __name__ == "__main__":

      lock = Lock()

      for i in range(10):

        p = Process(target=task,args=(i,lock))

        p.start()

    当多个进程共享一段数据的时候,数据会出现不安全的现象,需要加锁来维护数据的安全性

    lock =Lock()

    lock.acquire()  #拿钥匙

    print(1111)

    lock.release()  #还钥匙

    lock.acquire()  #阻塞,如果上面没有还钥匙就会阻塞

    print(2222)  

    7.信号量

    from multiprocessing import Process,Semaphore

    sef =Semaphore(3)  #信号量

    sem.acquire()

    print(1)

    sem.acquire()

    print(2)

    sem.acquire()

    print(3)

    sem.acquire()  #阻塞,因为只有三把钥匙,且上面没有还钥匙的过程

    print(4)

    import time,random

    from multiprocessing import Process,Semaphore

    def ktv(num,sem):

      sem.acquire()

      print("person %s 进了KTV"%num)

      time.sleep(random.randint(1,4))

      print("person %s 出来了"%num)

      sem.release()

    if __name__ == "__main__":

      sem = Semaphore(3)

      for i in range(10):

        p = Process(target=ktv,args=(i,sem))

        p.start()

    信号量的本质 : 多把钥匙对应一把锁,  lock + count计数

    8.事件

    并发的时候,很多模型,事件

    from multiprocessing import Event , Process

    wait() 方法 : 等待

    阻塞 :如果这个标志是False ,那么就是阻塞

    非阻塞:如果这个标志是True,那么就是非阻塞

    查看标志的方法: is_set()

    修改标志 : set()将标志设置为True

         clear()将标志设置为False

    e = Event()

    print(e.is_set())  #在事件的创建之初默认是False

    e.set()  #将标志设置为True

    print(e.is_set())

    e.wait()  #相当于什么都没有做pass,因为当前标志是True,非阻塞状态

    e.clear()  #将标志设置为False

    e.wait()  #永远阻塞

    e.wait(timeout = 10)#如果信号在阻塞10s之内变为True,那么不继续阻塞直接pass,如果阻塞10s之后代码继续执行,但是状态没有变.

    print(e.is_set())#无论前面的wait的timeout是否通过,我的状态都不会因此改变.

    红绿灯模型

    控制交通灯的过程

    import time,random

    from multiprocessing import Process,Event

    def traffic_light(e):  

      print("33[1;31m 红灯亮33[0m")

      while 1:

        time.sleep(2)

        if e.is_set():

          print("33[1;31m 红灯亮33[0m")

          e.clear()

        else:

          print("33[1;32m 绿灯亮33[0m")

          e.set()

    车 等或者通过

    def car(id,e):

      while 1:

        if not e.is_set():

          print("car %s 等待"%id)

          e.wait()

        print("car %s 通过"%id)

    def police_car(id,e):

      if not e.is_set():

        e.wait(timeout=0.5)

      print("police_car %s通过"%id)

    主进程  启动交通控制灯  启动车的进程

    if __name__ == "__main__":

      e = Event()

      Process(target=traffic_light,args = (e,))

      nl = [police_car,car]

      for i in range(20):

        p  =Process(target=random.choice(nl),args=(i,e))

        p.start()

        time.sleep(random.randrange(0,3,2))

    总结:

    进程之间的数据是隔离的

      进程与进程之间是不能自由的交换内存数据的

      全局的变量在子进程中修改 其他进程是感知不到的

    守护进程

      特点 : 生命周期只和主进程的代码有关系,和其他子进程没关系

      用处 : 报活

    多进程启动tcp协议的socket来完成并发

    进程的同步控制 -- 进程之间有一些简单的信号传递,用户是感知不到的,且用户不能传递自己想传递的内容

    锁    *****

    信号量   锁 + 计数器实现

    事件       wait

    事件 : 通过一个标记来控制多个进程进行同步控制

    在某个地方wait是否有阻塞的行为是根据事件对象内部的一个标记来决定的

    在事件对象中提供的方法可以修改这个标记的状态

            

  • 相关阅读:
    jenkins:用jenkins通过ssh部署jar包到远程linux机器(jdk 15 / jenkins 2.257)
    linux(centos8):安装java jdk 15 (java 15)
    38. 外观数列 迭代
    58. 最后一个单词的长度
    kmp字符串匹配
    单词规律
    1502. 判断能否形成等差数列
    1496. 判断路径是否相交
    1475. 商品折扣后的最终价格
    一维数组的动态和
  • 原文地址:https://www.cnblogs.com/fengkun125/p/9369206.html
Copyright © 2020-2023  润新知