一. 基本定义

  互斥锁(英语:英语:Mutual exclusion,缩写 Mutex)是一种用于多线程编程中,防止两条线程同时对同一公共资源(比如全局变量)进行读写的机制。该目的通过将代码切片成一个一个的临界区域(critical section)达成。临界区域指的是一块对公共资源进行访问的代码,并非一种机制或是算法。一个程序、进程、线程可以拥有多个临界区域,但是并不一定会应用互斥锁。

二. 互斥锁的作用

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

三. 互斥锁例子

  互斥锁常见的应用常见就是我们抢票的时候,10个同时查看到还有2张剩余票数.然后开始提交购票请求,但是能买到票的只有2个人.也就是说查看票数是并行操作,但是购票却是串行操作.

如果都是并行操作,那么数据就会造成10个人同时都在对剩余票数进行操作,将会导致2张票买给了10个人.所以,我们必须保证,串行操作,且下一个人操作的数据,是在上一个人操作后,已经更新的数据.

 from multiprocessing import Process,Lock
import time
import json def search(name):
time.sleep(1)
dic = json.load(open("db.txt","r",encoding="utf-8"))
print("<%s> 剩余票数:%s"%(name,dic["count"])) def get(name,mutex):
mutex.acquire() # 互斥锁加在这里,保证同时只能有一个人在购票.
time.sleep(1)
dic = json.load(open("db.txt","r",encoding="utf-8"))
if dic["count"]>0:
print("开始购票")
time.sleep(2)
dic["count"]-=1
json.dump(dic,open("db.txt","w",encoding="utf-8"))
print("<%s>购票成功."%name) else:
print("<%s>购票失败."%name)
mutex.release() # 释放互斥锁 def task(name,mutex):
search(name)
get(name,mutex)

互斥锁_模拟抢票

四. 互斥锁与join

  既然互斥锁的将原本并行执行才程序,变成了串行执行,那么我们之前学习的jion方法,不就可以完成这个操作吗?为什么还要用互斥锁呢?

  我们把刚刚的例子改成用jion的方法,看看会出现什么问题.  

from multiprocessing import Process,Lock
import time
import json def search(name):
time.sleep(1)
dic = json.load(open("db.txt","r",encoding="utf-8"))
print("<%s> 剩余票数:%s"%(name,dic["count"])) def get(name):
# mutex.acquire() # 互斥锁加在这里,保证同时只能有一个人在购票.
time.sleep(1)
dic = json.load(open("db.txt","r",encoding="utf-8"))
if dic["count"]>0:
print("开始购票")
time.sleep(2)
dic["count"]-=1
json.dump(dic,open("db.txt","w",encoding="utf-8"))
print("<%s>购票成功."%name) else:
print("<%s>购票失败."%name)
# mutex.release() # 释放互斥锁 def task(name):
search(name)
get(name) if __name__ == '__main__':
# mutex = Lock() #生成锁
for i in range(10):
p = Process(target=task,args=("路人%s"%i,))
p.start()
p.join()

join方法_模拟购票

<路人0> 剩余票数:2
开始购票
<路人0>购票成功.
<路人1> 剩余票数:1
开始购票
<路人1>购票成功.
<路人2> 剩余票数:0
<路人2>购票失败.
<路人3> 剩余票数:0
<路人3>购票失败.
<路人4> 剩余票数:0
<路人4>购票失败.
<路人5> 剩余票数:0
<路人5>购票失败.
<路人6> 剩余票数:0
<路人6>购票失败.
<路人7> 剩余票数:0
<路人7>购票失败.
<路人8> 剩余票数:0
<路人8>购票失败.
<路人9> 剩余票数:0
<路人9>购票失败.

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

五. 总结  

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

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

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

  2、需要自己加锁处理

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

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

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

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

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

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

六. 补充知识---Process对象的其他属性

p.daemon :守护进程(必须在开启之前设置守护进程):如果父进程死,子进程p也死了

p.join:父进程等p执行完了才运行主进程,是父进程阻塞在原地,而p仍然在后台运行。

terminate:强制关闭。(确保p里面没有其他子进程的时候关闭,如果里面有子进程,你去用这个方法强制关闭了就会产生僵尸进程(打个比方:如果你老子挂了,你还没挂,那么就没人给你收尸了,啊哈哈))

is_alive:关闭进程的时候,不会立即关闭,所以is_alive立刻查看的结果可能还是存活

p.join():父进程在等p的结束,是父进程阻塞在原地,而p仍然在后台运行

p.name:查看名字

p.pid :查看id

七. 队列Queue

  队列介绍:

  进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的

  创建队列的类(底层就是以管道和锁定的方式实现):

 Queue([maxsize]):创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。
参数介绍: maxsize是队列中允许最大项数,省略则无大小限制。
但需要明确:
1、队列内存放的是消息而非大数据
2、队列占用的是内存空间,因而maxsize即便是无大小限制也受限于内存大小
主要方法介绍: q.put方法用以插入数据到队列中。
q.full() 判断队列是否已经满了
q.get方法可以从队列读取并且删除一个元素。
q.empty() 判断队列是否已经没有数据了
 from multiprocessing import Queue

 q=Queue(3)

 q.put(1)
q.put(2)
q.put(3)
print(q.full()) #满了
# q.put(4) #再放就阻塞住了 print(q.get())
print(q.get())
print(q.get())
print(q.empty()) #空了
# print(q.get()) #再取就阻塞住了

队列例子

day 7-4 互斥锁与队列的更多相关文章

  1. Python并发编程03 /僵孤进程,孤儿进程、进程互斥锁,进程队列、进程之间的通信

    Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 目录 Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 1. 僵尸进程/孤儿进 ...

  2. [并发编程 - socketserver模块实现并发、[进程查看父子进程pid、僵尸进程、孤儿进程、守护进程、互斥锁、队列、生产者消费者模型]

    [并发编程 - socketserver模块实现并发.[进程查看父子进程pid.僵尸进程.孤儿进程.守护进程.互斥锁.队列.生产者消费者模型] socketserver模块实现并发 基于tcp的套接字 ...

  3. 守护进程,互斥锁,IPC,队列,生产者与消费者模型

    小知识点:在子进程中不能使用input输入! 一.守护进程 守护进程表示一个进程b 守护另一个进程a 当被守护的进程结束后,那么守护进程b也跟着结束了 应用场景:之所以开子进程,是为了帮助主进程完成某 ...

  4. 并发编程(二)--利用Process类开启进程、僵尸进程、孤儿进程、守护进程、互斥锁、队列与管道

    一.multiprocessing模块 1.multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似. 2.mu ...

  5. 并发编程(二)——利用Process类开启进程、僵尸进程、孤儿进程、守护进程、互斥锁、队列与管道

    Process类与开启进程.守护进程.互斥锁 一.multiprocessing模块 1.multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模 ...

  6. 【TencentOS tiny】深度源码分析(6)——互斥锁

    互斥锁 互斥锁又称互斥互斥锁,是一种特殊的信号量,它和信号量不同的是,它具有互斥锁所有权.递归访问以及优先级继承等特性,在操作系统中常用于对临界资源的独占式处理.在任意时刻互斥锁的状态只有两种,开锁或 ...

  7. 一种在获取互斥锁陷入阻塞时可以被中断的 lock

    经过上篇的实例 线程在陷入阻塞时,在sychronized获取互斥锁陷入阻塞时,我们是无法进行中断的,javase5中提供了一种解决的办法 ReentrantLock ,我们常常用到的是它的lock( ...

  8. Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型

    一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例 ...

  9. 互斥锁,IPC队列

    进程同步(锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,part1:共享同一打印终端,发现会有多行内容打印到一行的现象(多个进程共享并抢占同一个 ...

随机推荐

  1. ES5-ES6-ES7_字符串与JOSN格式的数据相互转换以及深度克隆新对象

    这篇文章主要来讲HTML5中的新方法:parse()把字符串转换成josn格式的数据和stringify()把josn格式的数据转换成字符串 eval()方法的回顾 eval()方法可以将任何字符串解 ...

  2. WPF设计の不规则窗体

    我们在工作中,经常会需要画一些不规则的窗体,现在总结如下. 一.利用VisualBrush实现.这依赖于VisualBrush的特性,任何控件可以作为画刷,而画刷又可以作为背景. 此种方法可以用于实现 ...

  3. flask基础入门

    Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后 ...

  4. centos7下kubernetes(2。kubernetes---start,重要概念)

    Cluster cluster是计算,存储和网络资源的集合,kubernetes是利用这些资源运行各种基于容器的应用 Master Master是cluster的大脑,他的主要职责是调度,即决定应用在 ...

  5. iptables snat 和dnat说明

    iptables中的snat和dnat是非常有用的,感觉他们二个比较特别,所以单独拿出来说一下. dnat是用来做目的网络地址转换的,就是重写包的目的IP地址.如果一个包被匹配了,那么和它属于同一个流 ...

  6. springboot RestTemplate请求

    每天学习一点点 编程PDF电子书.视频教程免费下载:http://www.shitanlife.com/code   1.定义 RestTemplateConfig 配置类 @Configuratio ...

  7. mysql 监控工具(windows版本)

    文章转自  https://www.cnblogs.com/wucj/p/7152020.html 工具下载  http://www.profilesql.com/download/

  8. 《Web接口开发与自动化测试 -- 基于Python语言》---现已出版。

    终于可以购买了!! 有需要的同学通过下面链接购买. 购买来链接: https://item.jd.com/11806319423.html 为什么要出这样一本书? 首先,今年我有不少工作是跟接口自动化 ...

  9. Pyhton2.x 和Python3.x

    一. 异常处理和pint区别 try: ...except Exception,e: # 2.x,3.x 需要把逗号(,)变为as. print e.message # 2.x,3.需要吧print内 ...

  10. zabbix API应用

    1.模拟登录 curl -i -X POST -H 'Content-Type:application/json' -d '{"jsonrpc":"2.0",& ...