标签(空格分隔): 互斥锁


进程之间的数据不共享,但是共享同一套文件系统,所以访问同一个文件,或者同一个打印终端,是没有问题的,而共享带来的问题就是竞争,竞争带来的结果就是错乱,如下:

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

如何控制,就是加锁处理。而互斥锁的意思就是互相排斥,如果把多个进程比喻为多个人,互斥锁的工作原理就是多个人都要去争抢同一个资源:卫生间,一个人抢到卫生间后上一把锁,其他人都要等着,等到这个完成任务后释放锁,其他人才有可能有一个抢到......所以互斥锁的原理,就是把并发改成穿行,降低了效率,但保证了数据安全不错乱

#由并发变成了串行,牺牲了运行效率,但避免了竞争
from multiprocessing import Process,Lock
import os,time
def work(lock):
lock.acquire() #加锁
print('%s is running' %os.getpid())
time.sleep(2)
print('%s is done' %os.getpid())
lock.release() #释放锁
if __name__ == '__main__':
lock=Lock()
for i in range(3):
p=Process(target=work,args=(lock,))
p.start()

模拟抢票练习:

多个进程共享同一文件,我们可以把文件当数据库,用多个进程模拟多个人执行抢票任务;

#文件db.txt的内容为:{"count":1}
#注意一定要用双引号,不然json无法识别
from multiprocessing import Process
import time,json def search(name):
dic=json.load(open('db.txt'))
time.sleep(1)
print('\033[43m%s 查到剩余票数%s\033[0m' %(name,dic['count'])) def get(name):
dic=json.load(open('db.txt'))
time.sleep(1) #模拟读数据的网络延迟
if dic['count'] >0:
dic['count']-=1
time.sleep(1) #模拟写数据的网络延迟
json.dump(dic,open('db.txt','w'))
print('\033[46m%s 购票成功\033[0m' %name) def task(name):
search(name)
get(name) if __name__ == '__main__':
for i in range(10): #模拟并发10个客户端抢票
name='<路人%s>' %i
p=Process(target=task,args=(name,))
p.start()

并发运行,效率高,但竞争写同一文件,数据写入错乱,只有一张票,卖成功给了10个人

<路人0> 查到剩余票数1

<路人1> 查到剩余票数1

<路人2> 查到剩余票数1

<路人3> 查到剩余票数1

<路人4> 查到剩余票数1

<路人5> 查到剩余票数1

<路人6> 查到剩余票数1

<路人7> 查到剩余票数1

<路人8> 查到剩余票数1

<路人9> 查到剩余票数1

<路人0> 购票成功

<路人4> 购票成功

<路人1> 购票成功

<路人5> 购票成功

<路人3> 购票成功

<路人7> 购票成功

<路人2> 购票成功

<路人6> 购票成功

<路人8> 购票成功

<路人9> 购票成功

加锁处理:购票行为由并发变成了串行,牺牲了运行效率,但保证了数据安全

#把文件db.txt的内容重置为:{"count":1}
from multiprocessing import Process,Lock
import time,json def search(name):
dic=json.load(open('db.txt'))
time.sleep(1)
print('\033[43m%s 查到剩余票数%s\033[0m' %(name,dic['count'])) def get(name):
dic=json.load(open('db.txt'))
time.sleep(1) #模拟读数据的网络延迟
if dic['count'] >0:
dic['count']-=1
time.sleep(1) #模拟写数据的网络延迟
json.dump(dic,open('db.txt','w'))
print('\033[46m%s 购票成功\033[0m' %name) def task(name,lock):
search(name)
with lock: #相当于lock.acquire(),执行完自代码块自动执行lock.release()
get(name) if __name__ == '__main__':
lock=Lock()
for i in range(10): #模拟并发10个客户端抢票
name='<路人%s>' %i
p=Process(target=task,args=(name,lock))
p.start()

执行结果:

<路人0> 查到剩余票数1

<路人1> 查到剩余票数1

<路人2> 查到剩余票数1

<路人3> 查到剩余票数1

<路人4> 查到剩余票数1

<路人5> 查到剩余票数1

<路人6> 查到剩余票数1

<路人7> 查到剩余票数1

<路人8> 查到剩余票数1

<路人9> 查到剩余票数1

<路人0> 购票成功

互斥锁与join

使用join可以将并发变成串行,互斥锁的原理也是将并发变成穿行,那我们直接使用join就可以了啊,为何还要互斥锁,说到这里我赶紧试了一下

#把文件db.txt的内容重置为:{"count":1}
from multiprocessing import Process,Lock
import time,json def search(name):
dic=json.load(open('db.txt'))
print('\033[43m%s 查到剩余票数%s\033[0m' %(name,dic['count'])) def get(name):
dic=json.load(open('db.txt'))
time.sleep(1) #模拟读数据的网络延迟
if dic['count'] >0:
dic['count']-=1
time.sleep(1) #模拟写数据的网络延迟
json.dump(dic,open('db.txt','w'))
print('\033[46m%s 购票成功\033[0m' %name) def task(name,):
search(name)
get(name) if __name__ == '__main__':
for i in range(10):
name='<路人%s>' %i
p=Process(target=task,args=(name,))
p.start()
p.join()

执行结果:

<路人0> 查到剩余票数1

<路人0> 购票成功

<路人1> 查到剩余票数0

<路人2> 查到剩余票数0

<路人3> 查到剩余票数0

<路人4> 查到剩余票数0

<路人5> 查到剩余票数0

<路人6> 查到剩余票数0

<路人7> 查到剩余票数0

<路人8> 查到剩余票数0

<路人9> 查到剩余票数0

发现使用join将并发改成穿行,确实能保证数据安全,但问题是连查票操作也变成只能一个一个人去查了,很明显大家查票时应该是并发地去查询而无需考虑数据准确与否,此时join与互斥锁的区别就显而易见了,join是将一个任务整体串行,而互斥锁的好处则是可以将一个任务中的某一段代码串行,比如只让task函数中的get任务串行

def task(name,):
search(name) # 并发执行 lock.acquire()
get(name) #串行执行
lock.release()

总结:

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

虽然可以用文件共享数据实现进程间通信,但问题是:

1、效率低(共享数据基于文件,而文件是硬盘上的数据)

2、需要自己加锁处理

因此我们最好找寻一种解决方案能够兼顾:

1、效率高(多个进程共享一块内存的数据)

2、帮我们处理好锁问题。

这就是mutiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道。

队列和管道都是将数据存放于内存中,而队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,因而队列才是进程间通信的最佳选择。

我们应该尽量避免使用共享数据,尽可能使用消息传递和队列,避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可获展性。

python网络编程之互斥锁的更多相关文章

  1. python网络编程中互斥锁与进程之间的通信

    一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...

  2. python 并发编程 多进程 互斥锁 目录

    python 并发编程 多进程 互斥锁 模拟抢票 互斥锁与join区别

  3. python 并发编程 多进程 互斥锁与join区别

    互斥锁与join 互斥锁和join都可以把并发变成串行 以下代码是用join实现串行 from multiprocessing import Process import time import js ...

  4. python网络编程--线程递归锁RLock

    一:死锁 所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进 ...

  5. python 并发编程 多线程 互斥锁

    互斥锁 并行变成串行,牺牲效率 保证数据安全,实现局部串行 保护不同的数据,应该加不同的锁 现在一个进程 可以有多个线程 所有线程都共享进程的地址空间 实现数据共享 共享带来问题就会出现竞争 竞争就会 ...

  6. python 并发编程 多进程 互斥锁

    运行多进程  每个子进程的内存空间是互相隔离的 进程之间数据不能共享的 一 互斥锁 但是进程之间都是运行在一个操作系统上,进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终 ...

  7. python 网络编程 IO多路复用之epoll

    python网络编程——IO多路复用之epoll 1.内核EPOLL模型讲解     此部分参考http://blog.csdn.net/mango_song/article/details/4264 ...

  8. 28、Python网络编程

    一.基于TCP协议的socket套接字编程 1.套接字工作流程 先从服务器端说起.服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客 ...

  9. Python 网络编程(二)

    Python 网络编程 上一篇博客介绍了socket的基本概念以及实现了简单的TCP和UDP的客户端.服务器程序,本篇博客主要对socket编程进行更深入的讲解 一.简化版ssh实现 这是一个极其简单 ...

随机推荐

  1. Django之视图Views

    视图 视图接受Web请求并且返回Web响应 视图就是一个python函数,被定义在views.py中 响应可以是一张网页的HTML内容,一个重定向,一个404错误等等 响应处理过程如下图: URLco ...

  2. py库: pyautogui (自动测试模块,模拟鼠标、键盘动作)

    PyAutoGUI 是一个人性化的跨平台 GUI 自动测试模块 pyautogui 库 2017-10-4 pip install pyautogui python pip.exe install p ...

  3. 《算法》第四章部分程序 part 14

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,两种 Prim 算法求最小生成树 ● 简单 Prim 算法求最小生成树 package package01; import edu.princeton ...

  4. .Net 上传文件和下载文件

    一.上传文件 1.普通的form表单提交 注意点: 请求方式必须为Post. form表单里必须设置enctype属性(enctype = "multipart/form-data" ...

  5. 2. instr用法

    跟oracle中的instr用法一样: SQL> select count(*) from t where instr(title,‟oracle‟)>0; COUNT(*) ———- 5 ...

  6. leetcode997

    class Solution: def findJudge(self, N: int, trust: 'List[List[int]]') -> int: if N==1 and len(tru ...

  7. <面试> PHP 常见算法

    排序算法 1. 冒泡排序(数组排序) 基本思想:对需要排序的数组从后往前(逆序)进行多遍的扫描,当发现相邻的两个数值的次序与排序要求的规则不一致时,就将这两个数值进行交换.这样每遍历一次,最小的数值就 ...

  8. 机器学习入门-文本特征-使用LDA主题模型构造标签 1.LatentDirichletAllocation(LDA用于构建主题模型) 2.LDA.components(输出各个词向量的权重值)

    函数说明 1.LDA(n_topics, max_iters, random_state)  用于构建LDA主题模型,将文本分成不同的主题 参数说明:n_topics 表示分为多少个主题, max_i ...

  9. Directshow 采集与FFDshow 冲突

    在使用Directshow 进行视频采集的时候,发现与本地安装的一个ffdshow有冲突. 见下图: 经过测试发现dshow 在设置采集媒体类型的时候,如果设置RGB32就会崩溃,如果设置RGB24就 ...

  10. WDA-3-ALV查询

    主要是梳理下WebDynpro For ABAP开发过程: 1.创建WebDynpro组件 2.创建WebDynpro应用 1.创建WebDynpro组件 1.1创建 路径:选择Package--&g ...