并发编程

并发编程

守护进程

若a为b的守护进程,a进程结束,b进程未结束,则会等待进程结束后结束整体进程;

​ b进程结束,a进程未结束,则会立即结束整体进程

Process.daemon = True  
from multiprocessing import Process
import time

def task():
    print('zi run')
    time.sleep(3)
    print('zi over')

if __name__ == '__main__':
    p = Process(target=task)
    p.daemon = True           # 将这个进程设置为了守护进程
    p.start()
    time.sleep(4)

    print('zhu over')

进程安全问题

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

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

  1. 将并行改成串行
  2. 互斥锁

互斥锁

互斥锁是为了让公共内容有序进行

互斥锁内的内容是串行,锁外面的内容还可以是并发

from multiprocessing import Lock
from multiprocessing import Process,Lock
import time,random

def task1(mutex):
    for i in range(10000):   # 锁外面的内容还是可以实现并发
        print(1)
    mutex.acquire()          # 加锁
    print('zi1 run')
    time.sleep(3)
    print('zi1 over')
    mutex.release()         # 解锁

def task2(mutex):
    for i in range(10000):
        print(2)
    mutex.acquire()        # 加锁
    print('zi2 run')
    time.sleep(3)
    print('zi2 over')
    mutex.release()      # 解锁

if __name__ == '__main__':
    mutex = Lock()        # 创建锁
    p1 = Process(target=task1,args=(mutex,))
    p2 = Process(target=task2, args=(mutex,))
    p1.start()
    p2.start()

Manager的使用

from multiprocessing import Process,Manager,Lock
import time

def task(data,lock):
    lock.acquire()
    num = data[0]
    time.sleep(0.2)
    data[0] = num - 1
    lock.release()

    print("子 over")


if __name__ == '__main__':

    d = [100]
    m = Manager() # 创建一个管理器
    syncdict = m.list(d) # 让管理器创建一个进程同步的字典

    # 创建一个锁
    lock = Lock()

    ps = []
    for i in range(10):
        p = Process(target=task,args=(syncdict,lock))
        p.start()
        ps.append(p)

进程队列

队列 先进先出

from multiprocessing import Queue

q = Queue(2) # 创建队列 并且同时只能存储2个元素
q.put(1)
q.put(2)

# q.put(3,block=True,timeout=3) # 默认是阻塞的 当容器中没有位置了就阻塞 直到有人从里面取走元素为止


print(q.get())
print(q.get())
print(q.get(block=True,timeout=3))# 默认是阻塞的 当容器中没有位置了就阻塞 直到有人存入元素为止

函数调用栈

通过函数调用函数

​ 最先执行的函数反而是最后结束的,最后执行的函数是最先结束的

def a():
    b()


def b():
    c()


def c():
    print('c')
    raise  Exception


a()

进程间通信几种方式

  1. 创建一个共享文件

    ​ 缺点:效率低

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

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

  2. 共享内存

    ​ 缺点:数据量不能太大

    ​ 优点:效率高

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

  3. 管道

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

  4. socket

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

posted @ 2019-07-09 15:15  X_solitude  阅读(156)  评论(0编辑  收藏  举报