zoukankan      html  css  js  c++  java
  • 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是否有阻塞的行为是根据事件对象内部的一个标记来决定的

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

            

  • 相关阅读:
    LeetCode 252. Meeting Rooms
    LeetCode 161. One Edit Distance
    LeetCode 156. Binary Tree Upside Down
    LeetCode 173. Binary Search Tree Iterator
    LeetCode 285. Inorder Successor in BST
    LeetCode 305. Number of Islands II
    LeetCode 272. Closest Binary Search Tree Value II
    LeetCode 270. Closest Binary Search Tree Value
    LeetCode 329. Longest Increasing Path in a Matrix
    LintCode Subtree
  • 原文地址:https://www.cnblogs.com/fengkun125/p/9369206.html
Copyright © 2011-2022 走看看