浅谈互斥锁与进程间的通信 (举例说明)
一、互斥锁
进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理。注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行的修改,没错,速度是慢了,牺牲了速度而保证了数据安全。
1.上厕所的小例子:你上厕所的时候肯定得锁门吧,有人来了看见门锁着,就会在外面等着,等你吧门开开出来的时候,下一个人才去上厕所。
二、模拟抢票(也是利用了互斥锁的原理 :LOCK互斥锁)
三、Process对象的其他属性
p.daemon :守护进程(必须在开启之前设置守护进程):如果父进程死,子进程p也死了
p.join:父进程等p执行完了才运行主进程,是父进程阻塞在原地,而p仍然在后台运行。
terminate:强制关闭。(确保p里面没有其他子进程的时候关闭,如果里面有子进程,你去用这个方法强制关闭了就会产生僵尸进程(打个比方:如果你老子挂了,你还没挂,那么就没人给你收尸了,啊哈哈))
is_alive:关闭进程的时候,不会立即关闭,所以is_alive立刻查看的结果可能还是存活
p.join():父进程在等p的结束,是父进程阻塞在原地,而p仍然在后台运行
p.name:查看名字
p.pid :查看id
四、进程间的三种通信(IPC)方式
方式一:队列(推荐使用)
进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的。
1.队列:队列类似于一条管道,元素先进先出
需要注意的一点是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态
2.队列分类
队列有很多种,但都依赖与模块queue
queue.Queue() #先进先出
queue.LifoQueue() #后进先出
queue.PriorityQueue() #优先级队列
queue.deque() #双线队列
创建队列的类(底层就是以管道和锁定的方式实现):
Queue([maxsize]):创建共享的进程队列,Queue是多进程安全的队列,
可以使用Queue实现多进程之间的数据传递
参数介绍:
1 maxsize是队列中允许最大项数,省略则无大小限制。
方法介绍:
应用
生产者和消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
基于队列实现生产者消费者模型
一个生产者和一个消费者(有两种方式):
1、q.put(None):生产者给放一个None进去
2、利用JoinableQueue
方式二:管道(不推荐使用,了解即可)
管道相当于队列,但是管道不自动加锁
方式三:共享数据(不推荐使用,了解即可)
共享数据也没有自动加锁的功能,所以还是推荐用队列的。感兴趣的可以研究研究管道和共享数据
相关视频;
Epoll的具体实现与epoll线程安全,互斥锁,自旋锁,CAS,原子操作
版权声明: 本文为 InfoQ 作者【ShenDu_Linux】的原创文章。
原文链接:【http://xie.infoq.cn/article/b98d34cae312e6f939d96e15e】。文章转载请联系作者。
评论