五:守护进程

正常情况下,主进程默认等待子进程调用结束之后再结束
守护进程在主进程所有代码执行完毕之后,自动终止
kill -9 进程号 杀死进程.

守护进程的语法:
进程对象.daemon = True
设置该进程为守护进程
必须要写在start()方法之前赋值
为主进程守护,主进程如果代码执行结束了,该守护进程自动结束

#(1)基本语法
#例:

from multiprocessing import Process
import time
def func():
print("子进程start")
time.sleep(1)
print("子进程end") if __name__ == "__main__":
p = Process(target=func)
p.daemon = True
p.start()
time.sleep(1)
print("主进程执行结束")

结果为:

子进程start

主进程执行结束

因为为守护主进程,主进程结束子进程立即结束

(2) 多个子进程的情况
当多个子进程并发执行时,默认主进程等待子进程
如果标记该子进程是守护进程
当主进程执行完毕所有代码之后,守护进程立刻终止
主进程的代码执行到最后一行,就意味着函数代码执行完毕,就应该杀掉守护进程
其他非守护进程继续正常执行,主进程仍然等待直到结束
最后主进程在真正的释放结束
#例:

from multiprocessing import Process
import time
def func1():
count = 1
while True:
print("*" * count)
time.sleep(0.5)
count +=1 def func2():
print("func2 start")
time.sleep(3)
print("func2 end") if __name__ == "__main__":
p1 = Process(target=func1)
p1.daemon = True
p1.start() p2 = Process(target=func2)
p2.start() print("主进程代码执行结束...")

运行结果为:

主进程代码执行结束...
func2 start
func2 end
(3)守护进程的实际作用:监控报活

#例:

from multiprocessing import Process
import time
def alive():
# 服务器向另外一个服务器发送消息
# 给监控服务器发送报活消息
# 如果监控服务器没有收到报活消息,就判定1号主机异常
while True:
print("1号服务主机...I am OK")
time.sleep(0.8) def func():
print("用来统计当前主机的服务器日志,打包变成文件")
time.sleep(3) if __name__ == "__main__":
p1 = Process(target=alive)
p1.daemon = True
p1.start() p2 = Process(target=func)
p2.start() # 模拟好比这个程序结束了,那么服务器挂掉了
p2.join()
print("... ... ...")

输出结果为:

1号服务主机...I am OK

用来统计当前主机的服务器日志,打包变成文件

1号服务主机...I am OK

1号服务主机...I am OK

1号服务主机...I am OK

... ... ...

首先由p2的阻塞,p2没有执行结束前,p2.join()后的主进程语句执行不了,等p2结束执行join后面的,然后主进程程序结束,在异步运行的p1守护进程随即结束运行。

六: 锁(Lock)

lock.acquire()# 上锁

lock.release()# 解锁

 

#同一时间允许一个进程上一把锁 就是Lock

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

#同一时间允许多个进程上多把锁 就是[信号量Semaphore]

信号量是锁的变形: 实际实现是 计数器 + 锁,同时允许多个进程上锁

# 互斥锁Lock:互斥锁就是进程的相互排斥
#谁先抢到自由,谁就上锁改资源内容,为了保证数据的同步性
#注意: 多个锁一起上,不开锁,会造成死锁,上锁和解锁是一对的

(1)锁的基本用法

from multiprocessing import Process, Lock
#例1:
# 创建一把锁
lock = Lock()
# 上锁
lock.acquire()
print("") # 解锁
lock.release() #例2:
# 死锁 : 只上锁,不解锁,会阻塞,产生死锁
lock.acquire()
print(111)
lock.release() print(222) lock.acquire()
print(333)
#lock.release()
lock.acquire()
print(444)

例2的输出结果没有444,因为没有上一个锁解一个锁,造成死锁

(1)模拟抢票软件

比如12306抢票软件,实际上是吧mysql数据库中的内容读出来先与存在redis 的内存中。
内存的读写的速度极快,不需要再刻意的加延迟等待,即可把该有的数据更新或者返回。
等待抢票的高峰期过了,在慢慢把内存中的数据更新回MySQL当中。

#例:(ticket内的内容为:{"count": 5},让十个人抢票)

from multiprocessing import Process,Lock
import json,time
# 读取票数,更新票数
def wr_info(sign,dic=None):
if sign == "r":
with open("ticket",mode="r",encoding="utf-8") as fp:
dic = json.load(fp)
return dic
elif sign == "w":
with open("ticket",mode="w",encoding="utf-8") as fp:
json.dump(dic,fp) # 获取实际抢票的逻辑
def get_ticket(person):
# 读取数据库的实际票数
dic = wr_info("r")
# with open("ticket",mode="r",encoding="utf-8") as fp:
# dic = json.load(fp)
time.sleep(0.5)
if dic['count'] > 0:
print("%s抢到票了" % (person))
dic["count"] -= 1
# 更新数据库
wr_info("w",dic)
# with open("ticket",mode="w",encoding="utf-8") as fp:
# json.dump(dic,fp)
else:
print("%s没有买到这个票" % (person)) # 用ticket来进行函数的统一调用
def ticket(person,lock):
# 查询票数
dic = wr_info("r")
# with open("ticket",mode="r",encoding="utf-8") as fp:
# dic = json.load(fp)
print("%s 查询余票 : %s" % (person,dic["count"]))
lock.acquire() # 开始抢票
get_ticket(person)
lock.release() if __name__ == "__main__":
lock = Lock()
for i in range(10):
p = Process(target=ticket,args=("person%s" % (i),lock) )
p.start() 

输出结果为:

person2 查询余票 : 5

person1 查询余票 : 5

person6 查询余票 : 5

person7 查询余票 : 5

person0 查询余票 : 5

person4 查询余票 : 5

person9 查询余票 : 5

person3 查询余票 : 5

person5 查询余票 : 5

person8 查询余票 : 5

person2抢到票了

person1抢到票了

person6抢到票了

person7抢到票了

person0抢到票了

person4没有买到这个票

person9没有买到这个票

person3没有买到这个票

person5没有买到这个票

person8没有买到这个票

查询剩余票数是并发的一起的,在抢票的时候也是一起抢的,谁抢到了就会对剩余票数进行更新,抢到票的就会对剩余票数加锁,已免数据错乱。

(3)区分同步和异步
# 在产生进程对象的时候,进程之间是异步,上锁之后,进程之间变成同步

from multiprocessing import Process,Lock
def func(num, lock):
lock.acquire()
print("走到上锁这个地方,变成一个同步程序,先来的进行先执行,后来的进程后执行,按次序依次执行")
print(num)
lock.release() if __name__ == "__main__":
# lock互斥锁, 进程之间数据不共享
# 但是lock对象底层是通过socket来互相发送数据,不管多少进程,都是同一个lock锁
lock = Lock()
for i in range(10):
p = Process(target=func, args=(i, lock))
# 1. 10个子进程异步执行,是并发操作
p.start()

七.Semaphore(信号量)

信号量Semaphore是一个计数器,控制对公共资源或者临界区域的访问量,信号量可以指定同时访问资源或者进入临界区域的进程数。每次有一个进程获得信号量时,计数器-1,若计数器为0时,其他进程就停止访问信号量,一直阻塞直到其他进程释放信号量。

上述讲的Lock,属于互斥锁,也就是一把钥匙配备一把锁,同时只允许锁住某一个数据。而信号量则是多把钥匙配备多把锁,也就是说同时允许锁住多个数据。

#例:

from multiprocessing import Process,Semaphore
import random,time def ktv(person,sem):
# 上锁
sem.acquire()
print("%s进入ktv唱歌" % (person))
time.sleep(random.randrange(3,8))
print("%s走出ktv离开" % (person))
# 解锁
sem.release() if __name__ == "__main__":
# 同一时间最多允许4个进程执行ktv任务,剩下的进程等待
sem = Semaphore(4)
for i in range(10):
p = Process( target=ktv,args=("person%s" %(i),sem))
p.start()

每次运行4个进程,打一次打印是:

person2进入ktv唱歌
person1进入ktv唱歌
person4进入ktv唱歌
person0进入ktv唱歌

紧接着:

person2进入ktv唱歌
person1进入ktv唱歌
person4进入ktv唱歌
person0进入ktv唱歌
person1走出ktv离开
person8进入ktv唱歌
person4走出ktv离开
person9进入ktv唱歌

最后所有打印为:

person2进入ktv唱歌
person1进入ktv唱歌
person4进入ktv唱歌
person0进入ktv唱歌
person1走出ktv离开
person8进入ktv唱歌
person4走出ktv离开
person9进入ktv唱歌
person2走出ktv离开
person3进入ktv唱歌
person0走出ktv离开
person6进入ktv唱歌
person9走出ktv离开
person7进入ktv唱歌
person8走出ktv离开
person5进入ktv唱歌
person3走出ktv离开
person6走出ktv离开
person5走出ktv离开
person7走出ktv离开

Python 之并发编程之进程中(守护进程(daemon)、锁(Lock)、Semaphore(信号量))的更多相关文章

  1. Python 之并发编程之线程中

    四.线程锁lock(线程的数据安全) 在数据量较大的时候,线程中的数据会被并发,所有数据会不同步,以至于数据会异常. 下面还介绍了两种的上锁方法. 例: from threading import T ...

  2. 《java并发编程实战》读书笔记10--显示锁Lock,轮询、定时、读写锁

    第13章 显示锁 终于看到了这本书的最后一本分,呼呼呼,真不容易.其实说实在的,我不喜欢半途而废,有其开始,就一定要有结束,否则的话就感觉哪里乖乖的. java5.0之前,在协调对共享对象的访问时可以 ...

  3. java并发编程(四)守护进程 线程阻塞的四种情况

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17099981 守护线程   Java中有两类线程:User Thread(用户线程).Da ...

  4. Python 3 并发编程多进程之守护进程

    Python 3 并发编程多进程之守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemo ...

  5. python 之 并发编程(守护进程、互斥锁、IPC通信机制)

    9.5 守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就立即终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic process ...

  6. python并发编程-进程理论-进程方法-守护进程-互斥锁-01

    操作系统发展史(主要的几个阶段) 初始系统 1946年第一台计算机诞生,采用手工操作的方式(用穿孔卡片操作) 同一个房间同一时刻只能运行一个程序,效率极低(操作一两个小时,CPU一两秒可能就运算完了) ...

  7. python并发编程之进程1(守护进程,进程锁,进程队列)

    进程的其他方法 P = Process(target=f,) P.Pid 查看进程号  查看进程的名字p.name P.is_alive()  返回一个true或者False P.terminate( ...

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

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

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

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

随机推荐

  1. CCF 试题编号: 201909-4 试题名称: 推荐系统

    这题是stl的综合应用,map要想快,直接上unordered_map,这样查询接近O(1),是不是很嗨皮. 思路其实还是很简单的,type+id做个Hash,由于set.insert的第一个返回值是 ...

  2. The Preliminary Contest for ICPC Asia Shanghai 2019 B Light bulbs (离散的差分)

    复杂度分析,询问一千次,区间长1e6,O(1e9)超时. 那么我们知道对于差分来说,没必要一个一个求,只需要知道区间长就可以了,所以我们定义结构体差分节点,一个头结点,一个尾节点. 这样tail.lo ...

  3. Servlet映射细节

    Servlet的映射细节: 1):一个Servlet程序(Web组件),可以配置多个<url-pattern>,表示一个Servlet有多个资源名称. <servlet-mappin ...

  4. 学习笔记(26)- plato-端到端模型-定闹钟

    今天用了定闹钟的场景语料,在plato框架尝试了端到端的模型. 本文先记录英文的训练过程,然后记录中文的训练过程. 训练端到端的模型 发现使用英文的模型,还是显示有中文,所以,新建目录,重新训练 1. ...

  5. Centos610快照克隆后网络配置

    VMware中安装的Centos610快照并克隆后网络配置 1.网卡配置 vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 HWADDR ...

  6. powerbuilder连接oracle数据库

    一.打开已经安装好的pb9.0,主界面菜单栏有个两个圆柱形就行数据库连接,点击database. 二.选择oracle版本,由于数据库版本是9i,可以使用084 oracle8/8i.右键--选择ne ...

  7. 跨域-CORS

    跨域:是浏览器为了安全而做出的限制策略 浏览器请求必须遵循同源策略:同域名,同端口,同协议 cors跨域- 服务器端设置,前端直接调用 说明:后台允许前端某个站点进行访问 后台设置 Access-Co ...

  8. Django安装数据库MySQLdb

    在使用Django搭建与树莓派智能终端时,使用mysql作为数据库管理,遇到如下问题: django.core.exceptions.ImproperlyConfigured: Error loadi ...

  9. 【原】mac电脑使用总结

    mac下终端配置(item2+oh-my-zsh)+solarized配色方案:https://www.cnblogs.com/weixuqin/p/7029177.html

  10. php虚拟主机配置( 输入网址 对应 ip地址)

    1.启动http_vhost.conf文件 在httpd-conf中,#virtual hosts 去掉前面的井号 # Includeconf/extra/httpd_vhost.conf 2.配置h ...