Day 32 并发编程2

Day 32 并发编程2

守护进程

守护进程由主进程创建,守护进程有一下两个特点:

  1. 守护进程会在主进程代码执行结束后就结束
  2. 守护进程内无法再开启子进程
from multiprocessing import Process,Lock
import time

def task1():
    print('task start')
    time.sleep(10)
    print('task end')

if __name__ == '__main__':
    p1=Process(target=task1)
    p1.daemon=True	#表示p1是主进程的守护进程
    p1.start()
    print('main start')
    time.sleep(2)
    print('main end')
    
        
main start
task start
main end

进程安全问题

当并发的多个任务要同时操作公共资源时,就是造成数据错乱的问题

解决方法就是讲并发操作编程串行操作,但是牺牲了效率,提升了安全性

  1. 将并行改成串行
from multiprocessing import Process

def task1():

        print("-------name is nick")
        print("-------gender is girl")
        print("-------age is 18")

def task2():

        print("++++++++name is bgon")
        print("++++++++gender is oldman")
        print("++++++++age is 48")

if __name__ == '__main__':
    p1 = Process(target=task1)
    p2 = Process(target=task2)

    p1.start()
    p1.join()
    p2.start()
  1. 互斥锁

互斥锁

互斥锁的原理就是将要操作的公共资源锁起来,保证同一时间只能有一个进程在执行这部分代码

什么是互斥锁:

互相排斥的锁

优点:可以将部分代码串行

缺点:必须保证只有一把锁

from multiprocessing import Process,Lock
import time,os

def task1(mutex):
    mutex.acquire()
    pid=os.getpid()
    print(f'task1 start {pid}')
    time.sleep(3)
    print(f'task1 end {pid}')
    mutex.release()

def task2(mutex):
    mutex.acquire()
    pid=os.getpid()
    print(f'task2 start {pid}')
    time.sleep(3)
    print(f'task2 end {pid}')
    mutex.release()

if __name__ == '__main__':
    mutex=Lock()
    p1 = Process(target=task1, args=(mutex,))
    p2 = Process(target=task2, args=(mutex,))
    p1.start()
    time.sleep(1)
    p2.start()
    
# 先执行完p1 p1解锁后再执行p2

from multiprocessing import Process,Lock
import time,os

def task1(mutex):
    # mutex.acquire()
    pid=os.getpid()
    print(f'task1 start {pid}')
    time.sleep(3)
    print(f'task1 end {pid}')
    # mutex.release()

def task2(mutex):
    # mutex.acquire()
    pid=os.getpid()
    print(f'task2 start {pid}')
    time.sleep(3)
    print(f'task2 end {pid}')
    # mutex.release()

if __name__ == '__main__':
    mutex=Lock()
    p1 = Process(target=task1, args=(mutex,))
    p2 = Process(target=task2, args=(mutex,))
    p1.start()
    # time.sleep(1)
    p2.start()

#上述代码就是并行p1 p2同时start 同时end

案例-抢票

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

JSON_PATH='ticket.json'
metux=Lock()

def show():
    with open(JSON_PATH,'r') as fr:
        data=json.load(fr)
        ticket_count=data["count"]
        print(ticket_count)

def buy():
    with open(JSON_PATH,'r') as fr:
        data=json.load(fr)
        print(data["count"])
        if data["count"]>=1:
            data["count"] -= 1
            with open(JSON_PATH,'w') as fw:
                json.dump(data,fw)
                print('抢票成功')

def buy_with_lock(metux):
    metux.acquire()
    buy()
    metux.release()

if __name__ == '__main__':
    for i in range (10):
        p=Process(target=buy_with_lock,args=(metux,))
        p.start()

IPC 队列

ipc指的就是进程间通信

进程间通信几种方式

  1. 创建一个共享文件

    ​ 缺点:效率低

    ​ 优点:理论上交换的数据量非常大

    ​ 适用于:交互不频繁但是数据量非常大的情况

  2. 共享内存

    ​ 缺点:数据量不能太大

    ​ 优点:效率高

    ​ 适用于:交互频繁,数据量较小

  3. 管道

    ​ 管道也是基于文件的,它是单向的,编程比较复杂

  4. socket

    ​ 编程复杂,更适用于基于网络来交换数据

共享内存的几种方式

  1. Manager

    可以为我们创建进程间同步的容器,但是没有处理安全问题,所以不常用

  2. Queue

    翻译为队列,是一种特殊的容易,特点是先进先出

  3. 栈也是一种特殊的容器,特点是先进后出

posted @ 2019-07-04 20:43  萨萌萌  阅读(207)  评论(0编辑  收藏  举报