zoukankan      html  css  js  c++  java
  • 进程互斥(锁)------------------>一个坑

    进程互斥锁

    引入:

      进程之间数据不共享,但是共享同一套文件系统(如硬盘、键盘、cpu等),所以访问同一个文件,或同一个打印终端,是没有问题的,竞争带来的结果就是错乱,如何控制,就是加锁处理,即进程加锁。

     1 #并发运行,效率高,但竞争同一打印终端,带来了打印错乱
     2 from multiprocessing import Process
     3 import os,time
     4 def work():
     5     print('%s is running' %os.getpid())
     6     time.sleep(2)
     7     print('%s is done' %os.getpid())
     8 
     9 if __name__ == '__main__':
    10     for i in range(3):
    11         p=Process(target=work)
    12         p.start()
    13 
    14 # 并发运行,效率高,但竞争同一打印终端,带来了打印错乱

    特点:

      1.某进程先获取到cpu资源之后,要立即上锁,避免其他人对资源的竞争,只有当该进程解锁(释放)之后,剩余的进程才能进行竞争。

      2.进程互斥锁使得程序的执行顺序成为串行,牺牲了效率,但提高了安全性。

      3.同一时刻只允许一个进程运行,其他进程只能等待。(这与后面的信号量相反,信号量允许多个进程同时运行)

    代码示例:

     1 from multiprocessing import Process,Lock
     2 import os,time
     3 def work(lock):
     4     lock.acquire() #上锁
     5     print('%s is running' %os.getpid())
     6     time.sleep(2)
     7     print('%s is done' %os.getpid())
     8     lock.release()#解锁
     9 if __name__ == '__main__':
    10     lock = Lock()#创建一个互斥锁对象
    11     for i in range(3):
    12         p=Process(target=work,args=(lock,))
    13         p.start()
    进程互斥锁

    互斥锁解决抢票问题:

     1 from  multiprocessing import Process,Lock
     2 import json
     3 import os
     4 import time
     5 import random
     6 
     7 def search():
     8     with open('db.txt',encoding='utf-8') as f:#在当前目录创建一个db.txt文件,并写入“ {"count":1} ” 
     9         dic=json.load(f)
    10         print('%s 剩余票数 %s' %(os.getpid(),dic['count']))
    11 
    12 def get():
    13     with open('db.txt',encoding='utf-8') as read_f:
    14         dic=json.load(read_f)
    15 
    16     if dic['count'] > 0:
    17         dic['count']-=1
    18         time.sleep(random.randint(1,3)) #模拟手速+网速
    19         with open('db.txt','w',encoding='utf-8') as write_f:
    20             json.dump(dic,write_f)
    21             print('%s 抢票成功' %os.getpid())
    22 
    23 def task(mutex):
    24     search()
    25     mutex.acquire()
    26     get()
    27     mutex.release()
    28 
    29 if __name__ == '__main__':
    30     mutex=Lock()
    31     for i in range(20):
    32         p=Process(target=task,args=(mutex,))
    33         p.start()
    34         p.join()

    总结:

      加锁可以保证多个进程修改同一块数据,但是同一时刻只允许一个进程对其修改,其他进程必须等待,即穿行修改,牺牲了效率,但保证了数据的安全性,但如果加锁的步骤增多,又会造成程序的复杂性。

    扩展:

      因此我们最好找寻一种解决方案能够兼顾:1、效率高(多个进程共享一块内存的数据)2、帮我们处理好锁问题。这就是mutiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道。队列和管道都是将数据存放于内存中队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,我们应该尽量避免使用共享数据,尽可能使用消息传递和队列,避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可获展性。

  • 相关阅读:
    【Unittest】unittest相关解说
    python中导入模块/包的几种方式
    工具网站
    mapstruct 入门指南
    springboot 全局异常处理器
    多线程读表-压缩成zip下载
    编译执行和解释执行的区别
    swagger常用注解说明
    springboot整合swagger
    springboot整合druid
  • 原文地址:https://www.cnblogs.com/liuyinzhou/p/7978359.html
Copyright © 2011-2022 走看看