111 python程序中的进程操作-多进程同步(mulitProcessing Lock锁)

通过学习,我们使用各种方法实现了程序的异步,让多个任务可以同时在几个进程中并发处理,他们之间的运行没有顺序,一旦开启也不受我们控制。尽管并发编程让我们能更加充分的利用IO资源,但是也给我们带来了新的问题:当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题。

一、锁的基础使用

1.1多个进程抢占数据资源

from multiprocessing import Process
import os
import time
import random

def work(n):
    print(f'{n,os.getpid()}is running')
    time.sleep(random.random())
    print(f'{n,os.getpid()} is end')

if __name__ == '__main__':
    for i in range(1,4):
        p = Process(target=work,args=(i,))
        p.start()

(1, 4212)is running
(2, 8856)is running
(3, 5680)is running
(3, 5680) is end
(1, 4212) is end
(2, 8856) is end

1.2使用锁维护执行顺序

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

def work(n,lock):
    lock.acquire()
    print(f'{n,os.getpid()}is running')
    time.sleep(random.random())
    print(f'{n,os.getpid()} is end')
    lock.release()

if __name__ == '__main__':
    lock = Lock()
    for i in range(1,4):
        p = Process(target=work,args=(i,lock))
        p.start()

(1, 13304)is running
(1, 13304) is end
(2, 7524)is running
(2, 7524) is end
(3, 14552)is running
(3, 14552) is end

上面这种情况虽然使用加锁的形式实现了顺序的执行,但是程序又重新变成串行了,这样确实会浪费了时间,却保证了数据的安全。

三、抢票小程序实列(锁实现数据安全和高效率)

3.1多进程同时抢票实例

我们以模拟抢票为例,来看看数据安全的重要性。

# 文件db的内容为:{"count":1}
# 注意一定要用双引号,不然json无法识别
# 并发运行,效率高,但竞争写同一文件,数据写入错乱
from multiprocessing import Process,Lock
import time,json,random
def search(i):
    time.sleep(1)
    dic=json.load(open('ad.txt'))
    print('子进程%s查看剩余票数%s' %(i,dic['count']))

def get():
    dic=json.load(open('ad.txt'))
    time.sleep(1)  # 模拟读数据的网络延迟
    if dic['count'] >0:
        dic['count']-=1
        time.sleep(0.2)  # 模拟写数据的网络延迟
        json.dump(dic,open('ad.txt','w'))
        print('购票成功')

def task(i):
    search(i)
    get()

if __name__ == '__main__':
    for i in range(1,15):  # 模拟并发15个客户端抢票
        p=Process(target=task,args=(i,))
        p.start()

子进程2查看剩余票数1
子进程3查看剩余票数1
子进程12查看剩余票数1
子进程7查看剩余票数1
子进程11查看剩余票数1
子进程13查看剩余票数1
子进程9查看剩余票数1
子进程8查看剩余票数1
子进程6查看剩余票数1
子进程14查看剩余票数1
子进程5查看剩余票数1
子进程1查看剩余票数1
子进程10查看剩余票数1
子进程4查看剩余票数1
购票成功
购票成功
购票成功
购票成功
购票成功
购票成功
购票成功
购票成功
购票成功
购票成功
购票成功
购票成功
购票成功
购票成功

并发运行,效率高,但竞争写同一文件,数据写入错乱

3.2 使用join方法来实现数据安全

如果使用join方法的话,那这样就是成了一个串行的概念了,这样只能保证数据的安全性,但是程序的效率问题并没有解决

from multiprocessing import Process,Lock
import time,json,random
def search():
    dic=json.load(open('db'))
    print('剩余票数%s' %dic['count'])

def get():
    dic=json.load(open('db'))
    if dic['count'] >0:
        dic['count']-=1
        time.sleep(0.2)  # 模拟写数据的网络延迟
        json.dump(dic,open('db','w'))
        print('购票成功')

def task():
    search()
    get()

if __name__ == '__main__':
    for i in range(1,15):  # 模拟并发15个客户端抢票
        p=Process(target=task)
        p.start()
        p.join()

子进程1查看剩余票数1
购票成功
子进程2查看剩余票数0
没有票了
子进程3查看剩余票数0
没有票了
子进程4查看剩余票数0
没有票了
子进程5查看剩余票数0
没有票了
子进程6查看剩余票数0
没有票了
子进程7查看剩余票数0
没有票了
子进程8查看剩余票数0
没有票了
子进程9查看剩余票数0
没有票了
子进程10查看剩余票数0
没有票了
子进程11查看剩余票数0
没有票了
子进程12查看剩余票数0
没有票了
子进程13查看剩余票数0
没有票了
子进程14查看剩余票数0
没有票了

*3.3 使用锁机制Lock来实现数据安全

加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。

import json
import time
from multiprocessing import Process, Lock

def check():
    with open('db.txt','r',encoding='utf8') as fr:
        res = json.load(fr)
        return res

def buy(i):
    with open('db.txt','r',encoding='utf8') as fr:
        res = json.load(fr)
    time.sleep(1)
    if res['count'] > 0:
        res['count'] -= 1
        with open('db.txt','w',encoding='utf8') as fw:
            json.dump(res,fw)
            print(f'进程{i}抢票成功')
        time.sleep(0.5) # 模拟网络io
    else:
        print(f'票已经售空!!!!')

def test(i,lock):
    res = check()
    print(f'还剩{res["count"]}张票!')

    lock.acquire() # 相当于锁头。锁住
    buy(i)
    lock.release() # 释放锁头

if __name__ == '__main__':
    lock = Lock() # 写在这里是为了每一个进程都拿到的是同一把锁
    for i in range(1,10):# 并发模拟10个子进程同时抢票
        p = Process(target=test,args=(i,lock))
        p.start()

        # 进程锁,是把锁住的代码编程了串行
        # join 是把所有的子进程编程了串行

还剩1张票!
还剩1张票!
还剩1张票!
还剩1张票!
还剩1张票!
还剩1张票!
还剩1张票!
还剩1张票!
还剩1张票!
进程5抢票成功
票已经售空!!!!
票已经售空!!!!
票已经售空!!!!
票已经售空!!!!
票已经售空!!!!
票已经售空!!!!
票已经售空!!!!
票已经售空!!!!

原文地址:https://www.cnblogs.com/xichenHome/p/11569043.html

时间: 2024-10-07 17:02:06

111 python程序中的进程操作-多进程同步(mulitProcessing Lock锁)的相关文章

Python程序中的进程操作-进程池(multiprocess.Pool)

Python程序中的进程操作-进程池(multiprocess.Pool) 一.进程池 为什么要有进程池?进程池的概念. 在程序实际处理问题过程中,忙时会有成千上万的任务需要被执行,闲时可能只有零星任务.那么在成千上万个任务需要被执行的时候,我们就需要去创建成千上万个进程么?首先,创建进程需要消耗时间,销毁进程也需要消耗时间.第二即便开启了成千上万的进程,操作系统也不能让他们同时执行,这样反而会影响程序的效率.因此我们不能无限制的根据任务开启或者结束进程.那么我们要怎么做呢? 在这里,要给大家介

Python程序中的进程操作-开启多进程(multiprocess.process)

目录 一.multiprocess模块 二.multiprocess.process模块 三.process模块介绍 3.1 方法介绍 3.2 属性介绍 3.3 在windows中使用process模块的注意事项 四.使用process模块创建进程 4.1 在Python中启动的第一个子进程 4.2 join方法 4.3 查看主进程和子进程的进程号 4.4 多个进程同时运行 4.5 多个进程同时运行,再谈join方法(1) 4.6 多个进程同时运行,再谈join方法(2) 4.7 通过继承Pro

110 python程序中的进程操作-开启多进程

之前我们已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,刚刚我们已经了解了,运行中的程序就是一个进程.所有的进程都是通过它的父进程来创建的.因此,运行起来的python程序也是一个进程,那么我们也可以在程序中再创建进程.多个进程可以实现并发效果,也就是说,当我们的程序中存在多个进程的时候,在某些时候,就会让程序的执行速度变快.以我们之前所学的知识,并不能实现创建进程这个功能,所以我们就需要借助python中强大的模块. 一.multiprocess模块 仔细说来,multipro

112 python程序中的进程操作-进程之间进行通信(mulitiProcessing Queue队列)

一.进程间通信 IPC(Inter-Process Communication) IPC机制:实现进程之间通讯 管道:pipe 基于共享的内存空间 队列:pipe+锁的概念--->queue 二.队列(Queue) 2.1 概念-----multiProcess.Queue 创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递. Queue([maxsize])创建共享的进程队列. 参数 :maxsize是队列中允许的最大项数.如果省略此参数,则无大小限制

113 python程序中的进程操作-进程间数据共享(multiProcess.Manger)

一.进程之间的数据共享 展望未来,基于消息传递的并发编程是大势所趋 即便是使用线程,推荐做法也是将程序设计为大量独立的线程集合,通过消息队列交换数据. 这样极大地减少了对使用锁定和其他同步手段的需求,还可以扩展到分布式系统中. 但进程间应该尽量避免通信,即便需要通信,也应该选择进程安全的工具来避免加锁带来的问题. 以后我们会尝试使用数据库来解决现在进程之间的数据共享问题. 1.1 Manager模块介绍 虽然进程间数据独立,但可以通过Manager实现数据共享,事实上Manager的功能远不止于

Python程序中的进程操作-进程同步(multiprocess.Lock)

目录 一.锁--multiprocess.Lock 一.锁--multiprocess.Lock 原文地址:https://www.cnblogs.com/nickchen121/p/11130253.html

Python程序中的线程操作-锁

Python程序中的线程操作-锁 一.同步锁 1.1多个线程抢占资源的情况 from threading import Thread import os,time def work(): global n temp=n time.sleep(0.1) n=temp-1 if __name__ == '__main__': n=100 l=[] for i in range(100): p=Thread(target=work) l.append(p) p.start() for p in l:

Python程序中的线程操作-concurrent模块

Python程序中的线程操作-concurrent模块 一.Python标准模块--concurrent.futures 官方文档:https://docs.python.org/dev/library/concurrent.futures.html 二.介绍 concurrent.futures模块提供了高度封装的异步调用接口 ThreadPoolExecutor:线程池,提供异步调用 ProcessPoolExecutor:进程池,提供异步调用 两者都实现相同的接口,该接口由抽象Execut

Python程序中的线程操作(线程池)-concurrent模块

目录 Python程序中的线程操作(线程池)-concurrent模块 一.Python标准模块--concurrent.futures 二.介绍 三.基本方法 四.ProcessPoolExecutor 五.ThreadPoolExecutor 六.map的用法 七.回调函数 Python程序中的线程操作(线程池)-concurrent模块 一.Python标准模块--concurrent.futures 官方文档:https://docs.python.org/dev/library/con