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


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

#并发运行,效率高,但竞争同一打印终端,带来了打印错乱
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. 重新配置dbconsole的步骤

    重新配置dbconsole的步骤emca -repos dropemca -repos createemca -config dbcontrol dbemctl start dbconsole

  2. Linux设置DNS server

    查看: cat /etc/resolv.conf 修改: vim /etc/resolv.conf

  3. openx

    1openx 插件开发——终端用 2openx _金额 3openx ————带整理 4openx url 5Openx 2.8.x 在php5.4.x下数据统计不能正常显示解决方案 6openx改造 ...

  4. hdfs standby namenode checkpoint 的一些参数

    dfs.namenode.checkpoint.period --两次检查点创建之间的固定时间间隔,默认3600,即1小时.所以去ann snn 看到的fsimage 相隔1个小时. dfs.name ...

  5. hive 索引

    hive 有限的支持索引,不支持主键外键,可以对表添加索引,也可以为某个分区添加索引.维护索引也要额外的存储空间和计算资源. 创建索引需要指定索引处理器 如 as 'org.apache.hadoop ...

  6. Asp.net Webform的页面生命周期

    1.分析请求的资源路径,寻找目录中对应的资源文件,若无法找到资源文件,则返回404错误2.分析资源文件的Page命令,通过Page指令找到代码文件和类 3.将页面文件和类一起编译生成最终的类(仅仅在第 ...

  7. Android Camera2的使用

    参考:https://developer.android.com/reference/android/hardware/camera2/package-summary.html camera2提供了一 ...

  8. CentOS7 安装 Mongodb 与 NodeJs 主要心得

    一.mongodb 1.安装 由于使用yum源下载安装总是超时,所以选择了tarball方式安装. 官方安装方法链接,https://docs.mongodb.com/manual/tutorial/ ...

  9. Linux 配置开机自启 和 修改环境变量

    [ 操作系统 Centos7 ] 一,开机自动启动的配置 1,赋予 /etc/rc.local 的执行权限 => chmod +x /etc/rc.local 2,在 /etc/rc.local ...

  10. CustomJSProperties珍藏版。目的是减少客户端的代码数量,但是又能将服务器数据传输给客户端。关键是:数据是实时更新的!!!!

    [这是帮助文档的说明] CustomJSProperties EventThe CustomJSProperties event fires each time a control callback ...