一、守护进程
之前我们讲的子进程是不会随着主进程而结束的,子进程全部执行完之后,程序才结束,那么如果有
一天我们的需求是我的主进程结束了,由主进程创建的子进程必须跟着结束,怎么办?守护进程就来了!
主进程创建守护进程
其一:守护进程会在主进程代码执行结束后就终止
其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children
注意:进程之间是互相独立的,主程序代码运行结束,守护进程随即终止

1 import os
2 import time
3 from multiprocessing import Process
4
5 class Myprocess(Process):
6 def __init__(self,person):
7 super().__init__()
8 self.person = person
9 def run(self):
10 print(os.getpid(),self.name)
11 print('%s正在和女主播聊天' %self.person)
12 time.sleep(3)
13 if __name__ == '__main__':
14 p=Myprocess('太白')
15 p.daemon=True #一定要在p.start()前设置,设置p为守护进程,禁止p创建子进程,并且父进程代码执行结束,p即终止运行
16 p.start()
17 # time.sleep(1) # 在sleep时linux下查看进程id对应的进程ps -ef|grep id
18 print('主')
二、进程同步(锁)
我们之前实现了进程的异步,让多个任务可以同时在几个进程中并发处理,他们之间的运行时没有顺序的,一旦
开启也不受我们控制。尽管并发编程让我们能更加充分的利用IO资源,但是也给我们带来了新的问题:进程之间数据
不共享。虽然可以共享同一台文件系统,所以访问同一个文件,或者同一个打印红缎,是没有问题的,而共享带来的是
竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理。

1 import os
2 import time
3 import random
4 from multiprocessing import Process
5
6 def work(n):
7 print('%s: %s is running' %(n,os.getpid()))
8 time.sleep(random.random())
9 print('%s:%s is done' %(n,os.getpid()))
10
11 if __name__ == '__main__':
12 for i in range(5):
13 p=Process(target=work,args=(i,))
14 p.start()
15
16 # 看结果:通过结果可以看出两个问题:问题一:每个进程中work函数的第一个打印就不是按照我们for循环的0-4的顺序来打印的
17 #问题二:我们发现,每个work进程中有两个打印,但是我们看到所有进程中第一个打印的顺序为0-2-1-4-3,但是第二个打印没有按照这个顺序,变成了2-1-0-3-4,说明我们一个进程中的程序的执行顺序都混乱了。
18 #问题的解决方法,第二个问题加锁来解决,第一个问题是没有办法解决的,因为进程开到了内核,有操作系统来决定进程的调度,我们自己控制不了
19 # 0: 9560 is running
20 # 2: 13824 is running
21 # 1: 7476 is running
22 # 4: 11296 is running
23 # 3: 14364 is running
24
25 # 2:13824 is done
26 # 1:7476 is done
27 # 0:9560 is done
28 # 3:14364 is done
29 # 4:11296 is done

1 #由并发变成了串行,牺牲了运行效率,但避免了竞争
2 from multiprocessing import Process,Lock
3 import os,time
4 def work(n,lock):
5 #加锁,保证每次只有一个进程在执行锁里面的程序,这一段程序对于所有写上这个锁的进程,大家都变成了串行
6 lock.acquire()
7 print('%s: %s is running' %(n,os.getpid()))
8 time.sleep(1)
9 print('%s:%s is done' %(n,os.getpid()))
10 #解锁,解锁之后其他进程才能去执行自己的程序
11 lock.release()
12 if __name__ == '__main__':
13 lock=Lock()
14 for i in range(5):
15 p=Process(target=work,args=(i,lock))
16 p.start()
17
18 #打印结果:
19 # 2: 10968 is running
20 # 2:10968 is done
21 # 0: 7932 is running
22 # 0:7932 is done
23 # 4: 4404 is running
24 # 4:4404 is done
25 # 1: 12852 is running
26 # 1:12852 is done
27 # 3: 980 is running
28 # 3:980 is done
29
30 #结果分析:(自己去多次运行一下,看看结果,我拿出其中一个结果来看)通过结果我们可以看出,多进程刚开始去执行的时候,每次运行,首先打印出来哪个进程的程序是不固定的,但是我们解决了上面打印混乱示例代码的第二个问题,那就是同一个进程中的两次打印都是先完成的,然后才切换到下一个进程去,打印下一个进程中的两个打印结果,说明我们控制住了同一进程中的代码执行顺序,如果涉及到多个进程去操作同一个数据或者文件的时候,就不担心数据算错或者文件中的内容写入混乱了。
上面这种情况虽然用加锁的形式是险恶熟悉怒的执行,但是程序又重新变成串行了,这样确实会浪费了时间
但是却保证了数据安全
接下来,模拟抢票为例,来看看数据安全的重要性。

1 #注意:首先在当前文件目录下创建一个名为db的文件
2 #文件db的内容为:{"count":1},只有这一行数据,并且注意,每次运行完了之后,文件中的1变成了0,你需要手动将0改为1,然后在去运行代码。
3 #注意一定要用双引号,不然json无法识别
4 #并发运行,效率高,但竞争写同一文件,数据写入错乱
5 from multiprocessing import Process,Lock
6 import time,json,random
7
8 #查看剩余票数
9 def search():
10 dic=json.load(open('db')) #打开文件,直接load文件中的内容,拿到文件中的包含剩余票数的字典
11 print('