python网络编程之互斥锁

时间:2022-11-02 22:24:16

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


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

#并发运行,效率高,但竞争同一打印终端,带来了打印错乱
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. ---awk 调shell 命令的方法

    cat /etc/passwd | awk -F: '/root/{ system ("echo "$1) }'

  2. Java中的逆变与协变

    看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); ...

  3. 网页制作技巧&colon;iframe自适应高度

    转自:http://www.enet.com.cn/article/2012/0620/A20120620126237.shtml 通过Google搜索iframe 自适应高度,结果5W多条,搜索if ...

  4. phpcms V9静态判断会员登录状态的方法

    phpcms v9如何在任意地方判断会员的登录状态呢?在php中是比较好判断的,代码如下 <?php if (!$_userid){ echo"会员没有登录"; }else ...

  5. Android中使用OKHttp上传图片,从相机和相册中获取图片并剪切

    效果:注意:1:网络权限<;;;); intent.putExtra(); ); intent.putExtra(); intent.putExtra(, byteArrayOutputStre ...

  6. Docker最全教程——从理论到实战(二)

    上篇内容链接: https://www.cnblogs.com/codelove/p/10030439.html Docker和ASP.NET Core Docker 正在逐渐成为容器行业的事实标准, ...

  7. luogu5012 水の数列 &lpar;并查集&plus;线段树&rpar;

    如果我们能求出来每个区间个数的最大分值,那就可以用线段树维护这个东西 然后出答案了 然后这个的求法和(luogu4269)Snow Boots G非常类似,就是我们把数大小排个序,每次都拿<=x ...

  8. create-react-app入门教程

    Create React App是FaceBook的React团队官方出的一个构建React单页面应用的脚手架工具.它本身集成了Webpack,并配置了一系列内置的loader和默认的npm的脚本,可 ...

  9. OO第一阶段总(休)结(养)分(生)析(息)

    第一次作业: 这是一次让我认识到ddl面前潜力真的可以无限大的作业. 一直以为OO是一门和数据结构一样先用几周的时间讲讲Java然后写写”Hello World”小程序再开始讲正课的我(我也不知道为什 ...

  10. TFS &lpar;Team Foundation Server&rpar; 2013集成Maven构建

    Team Foundation Server原生就支持跨平台的构建,包括Ant和Maven两种构建方式.通过配置构建服务器,连接TFS源代码库,可以实现持续集成构建,自动检测代码库健康状况,进而实现自 ...