python进程数据隔离,守护进程,锁,信号量和事件

主要内容:

# Process
# 1.进程之间的数据隔离问题
# 2.守护进程

# 几个进程的模型 ---- 进程同步的工具
# 有先后顺序 就是同步
# 进程之间 就是异步
# 希望原本异步的多进程操作,维持一个顺序 -- 同步工具
# 3.锁 Lock *****
# 4.信号量 Semaphore ***
# 5.事件 Event **

 

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

from multiprocessing import Process

n = 100
def fun():
    global  n
    n -= 1
    
    return n
if __name__ == '__main__':
    p = Process(target=fun)
    p.start()
    print(n)

"""
# 进程与进程之间的数据是隔离的
# 内存空间是不能共享的
# 所以要想进行通信,必须借助其他手段
# 且这两个进程都是自愿的

# 子进程的执行结果父进程获取不到
# 父进程依赖子进程的执行结果呢
# 父进程如何获取子进程的执行结果???
    # 父子进程之间通过socket通信
"""

 

2.守护进程

# 设置成守护进程之后 会有什么效果呢?
# 守护进程会在主进程的代码执行完毕之后直接结束,无论守护进程是否执行完毕

from multiprocessing import Process
import time


def fun():
    print("start")
    time.sleep(3)
    print("这是一个好天气")

if __name__ == '__main__':
    p = Process(target=fun)
    p.daemon = True
    # 守护进程的属性,默认是False,如果设置成True,就表示设置这个子进程为一个守护进程
    # 设置守护进程的操作应该在开启子进程之前
    p.start()
    time.sleep(1)
    print("主进程结束了!")

    # 设置成守护进程之后 会有什么效果呢?
    # 守护进程会在主进程的代码执行完毕之后直接结束,无论守护进程是否执行完毕

 

关于守护进程的一个需要注意的点,示例如下:(注意下面的fun2里面的in fun2只运行了两次,是跟随主函数的)

import time
from multiprocessing import Process

def fun():
    print("start")
    time.sleep(3)
    print("今天天气不错")
def fun2():
    while True:
        print("in fun2")
        time.sleep(0.5)

if __name__ == '__main__':
    p = Process(target=fun)
    p.start()
    p = Process(target=fun2)
    p.daemon = True
    p.start()
    time.sleep(1)
    print("主程序结束了")

"""
运行结果如下:
in fun2
start
in fun2
主程序结束了
今天天气不错
"""

守扩应用主要有如下功能.:

    # 报活 主进程还活着
    # 100台机器 100个进程  10000进程
    # 应用是否在正常工作 - 任务管理器来查看
    # 守护进程如何向监测机制报活???send/写数据库
    # 为什么要用守护进程来报活呢?为什么不用主进程来工作呢???
        # 守护进程报活几乎不占用CPU,也不需要操作系统去调度
        # 主进程能不能严格的每60s就发送一条信息

 

下面是多进程起socket的实例:


import socket
from multiprocessing import Process
def fun(conn):
try:
while 1:
ret = conn.recv(1024)
print(ret)
conn.send(b"hi")
except ConnectionAbortedError:
pass
finally:
conn.close()
if __name__ == '__main__':

sk = socket.socket()
ip_addr=("127.0.0.1",9000)
sk.bind(ip_addr)
sk.listen()
try:
while True:
conn,addr = sk.accept()
Process(target=fun,args=(conn,)).start()
finally:
sk.close()
 

锁:

# 锁
# lock = Lock() # 创造了一把锁
# lock.acquire() # 获取了这把锁的钥匙
# lock.release() # 归还这把锁的钥匙

锁的示例:

import time,json
from multiprocessing import Lock
from multiprocessing import Process

def search(i):
    with open("db","r") as f :content = json.load(f)
    time.sleep(0.2)
    print("第%s个用户正在查看,还剩%s个票"%(i,content["count"]))
def buy(i):
    with open("db","r") as f :content = json.load(f)
    time.sleep(0.2)
    print("第%s个用户正在查看,还剩%s个票"%(i,content["count"]))
    if content["count"] > 0:
        print("第%s个用户购票成功!"%i)
        content["count"] -= 1
        with open("db","w") as f : json.dump(content,f)
def test(i,lock):
    search(i)
    lock.acquire()
    buy(i)
    lock.release()

if __name__ == '__main__':
    lock = Lock()
    # lock.acquire()
    # lock.
    for i in range(10):
        Process(target=test,args=(i,lock)).start()

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

 信号量

# 信号量的本质
    # 多把钥匙对应一把锁
    # lock+count计数
互斥锁同时只允许一个线程更改数据,而信号量Semaphore是同时允许一定数量的线程更改数据 。
假设商场里有4个迷你唱吧,所以同时可以进去4个人,如果来了第五个人就要在外面等待,等到有人出来才能再进去玩。
实现:
信号量同步基于内部计数器,每调用一次acquire(),计数器减1;每调用一次release(),计数器加1.当计数器为0时,acquire()调用被阻塞。这是迪科斯彻(Dijkstra)信号量概念P()和V()的Python实现。信号量同步机制适用于访问像服务器这样的有限资源。
信号量与进程池的概念很像,但是要区分开,信号量涉及到加锁的概念

 

示例代码:

import os,time,random
from multiprocessing import Process,Semaphore
def go_ktv(sem,user):
    sem.acquire()
    print("%s在ktv中" % user)
    time.sleep(random.randint(3,10))
    print("%s走出了ktv"%user)
    sem.release()

if __name__ == '__main__':
    sem = Semaphore(2)
    for i in range(10):
        Process(target=go_ktv,args=(sem,i)).start()

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

 

 

事件:

python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。

    事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。

clear:将“Flag”设置为False
set:将“Flag”设置为True

 示例代码:

import time
import random
from multiprocessing import Process,Event
def ligth(e):
    print("\033[1;31m 红灯亮\033[0m")
    while True:
        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):
    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=ligth,args=(e,)).start()
    for i in range(10):
        Process(target=car,args=(i,e)).start()
        time.sleep(random.randrange(0, 3, 2))

 

posted @ 2018-07-25 15:19  auxiaoliu  阅读(334)  评论(0编辑  收藏  举报