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("\033[1;31m 红灯亮\033[0m")

 

  while 1:

    time.sleep(2)

    if e.is_set():

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

      e.clear()

    else:

      print("\033[1;32m 绿灯亮\033[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是否有阻塞的行为是根据事件对象内部的一个标记来决定的

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

        

 

posted @ 2018-07-26 16:30  冯坤大神  阅读(469)  评论(0编辑  收藏  举报