2018年5月19日笔记

时间:2022-09-22 17:27:22
  • 进程的概念

进程是程序在计算机上的一次执行活动。

进程可分为系统进程和用户进程。

所有正在运行的进程轮流使用CPU,任何一个时间点有且只有一个进程占用CPU。

 

 

  • 进程与线程的区别

进程 > 线程

多进程使用CPU的多个核,适合运算密集型

多线程使用CPU的一个核,核心IO密集型

 

 

  • python多进程 —— muiltiprocessing模块

python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程。Python提供了multiprocessing。

Multiprocessing支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。

 

 

  • 创建一个Process实例
p1 = multiprocessing.Process(target=func, args=(2,))

target=函数名字

args=函数所需的参数,以tuple形式传入,必须有逗号,注意单个参数的形式

 

multiprocessing的2个常用方法:

multiprocessing.cpu_count()     # 1. 统计CPU总数

multiprocessing.active_children()       # 2. 获取所有子进程

 

 

  • Process实例的常用属性和方法

常用属性:

p1 = multiprocessing.Process(target=func, args=(2,))
p1.name     # 进程名字
p1.pid      # 进程ID

 

常用方法:

p1 = multiprocessing.Process(target=func, args=(2,))
p1.is_alive()       # 判断进程是否存活
p1.run()            # 启动进程(不常用)
p1.start()          # 启动进程,自动调用run()方法(常用)
p1.join(timeout=5)  # 等待进程结束或直到超时(5s)

 

 

  • 习题1
 1 import multiprocessing
 2 import time
 3 
 4 
 5 def worker(args, interval):
 6     print("start worker {0}".format(args))
 7     time.sleep(interval)
 8     print("end worker {0}".format(args))
 9 
10 def main():
11     print("start main")
12     p1 = multiprocessing.Process(target=worker, args=(1, 1))
13     p2 = multiprocessing.Process(target=worker, args=(2, 2))
14     p3 = multiprocessing.Process(target=worker, args=(3, 3))
15     p1.start()
16     p2.start()
17     p3.start()
18     print("end main")
19 
20 if __name__ == '__main__':
21     main()
start main
end main
start worker 1
start worker 2
start worker 3
end worker 1
end worker 2
end worker 3

 

 

  • 习题2
 1 import multiprocessing
 2 import time
 3 
 4 def worker(args, interval):
 5     print("start worker {0}".format(args))
 6     time.sleep(interval)
 7     print("end worker {0}".format(args))
 8 
 9 def main():
10     print("start main")
11     p1 = multiprocessing.Process(target=worker, args=(1, 1))
12     p2 = multiprocessing.Process(target=worker, args=(2, 2))
13     p3 = multiprocessing.Process(target=worker, args=(3, 3))
14     p1.start()
15     p1.join(timeout=0.5)
16     p2.start()
17     p3.start()
18     print("the number of CPU is: {0}".format(multiprocessing.cpu_count()))
19     for p in multiprocessing.active_children():
20        print("The name of active children is: {0}, pid is: {1} is alive".format(p.name, p.pid))
21     print("end main")
22 
23 if __name__ == '__main__':
24     main()
start main
start worker 1
the number of CPU is: 4
The name of active children is: Process-1, pid is: 1348 is alive
The name of active children is: Process-3, pid is: 1350 is alive
The name of active children is: Process-2, pid is: 1349 is alive
end main
start worker 2
start worker 3
end worker 1
end worker 2
end worker 3

 

 

  • Lock组件

使用多进程来读写文件时,读和写不能同时进行,为了这种多个进程共享同一资源的场景不出问题,引入了锁机制。

锁有两种状态:被锁(locked)和没有被锁(unlocked)。拥有acquire()和release()两种方法,并且遵循一下的规则:

  • 如果一个锁的状态是unlocked,调用acquire()方法改变它的状态为locked
  • 如果一个锁的状态是locked,acquire()方法将会阻塞,直到另一个线程调用release()方法释放了锁;
  • 如果一个锁的状态是unlocked调用release()会抛出RuntimeError异常;
  • 如果一个锁的状态是locked,调用release()方法改变它的状态为unlocked。

 

 

  • 习题3
 1 import multiprocessing
 2 import time
 3 
 4 def add1(lock, value, number):
 5     with lock:
 6         print("start add1 number= {0}".format(number))
 7         for i in range(1, 5):
 8             number += value
 9             time.sleep(0.3)
10             print("number = {0}".format(number))
11 
12 def add3(lock, value, number):
13     lock.acquire()
14     print("start add3 number= {0}".format(number))
15     try:
16         for i in range(1, 5):
17             number += value
18             time.sleep(0.3)
19             print("number = {0}".format(number))
20     except Exception as e:
21         raise e
22     finally:
23         lock.release()
24         pass
25 
26 if __name__ == '__main__':
27     print("start main")
28     number = 0
29     lock = multiprocessing.Lock()
30     p1 = multiprocessing.Process(target=add1, args=(lock, 1, number))
31     p3 = multiprocessing.Process(target=add3, args=(lock, 3, number))
32     p1.start()
33     p3.start()
34     print("end main")
start main
end main
start add1 number= 0
number = 1
number = 2
number = 3
number = 4
start add3 number= 0
number = 3
number = 6
number = 9
number = 12

 

 

  • 多进程间可共享内存

multiprocessing模块提供了共享内存的操作。

一般的变量在进程之间是无法通信的,multiprocessing提供了Value和Array模块,实现了进程间的数据共享。

Python中还提供了强大的Manager模块专门来做数据共享,其支持的类型非常多,包括Value, Array, list, dict, Queue, Lock等。

 

 

  • 习题4
 1 import multiprocessing
 2 from multiprocessing import Value, Array, Manager
 3 import time
 4 
 5 
 6 def add1(value, number):
 7     print("start add1 number= {0}".format(number.value))
 8     for i in range(1, 5):
 9         number.value += value
10         print("number = {0}".format(number.value))
11 
12 def add3(value, number):
13     print("start add3 number= {0}".format(number.value))
14     try:
15         for i in range(1, 5):
16             number.value += value
17             print("number = {0}".format(number.value))
18     except Exception as e:
19         raise e
20 
21 if __name__ == '__main__':
22     print("start main")
23     number = Value('d', 0)
24     p1 = multiprocessing.Process(target=add1, args=(1, number))
25     p3 = multiprocessing.Process(target=add3, args=(3, number))
26     p1.start()
27     p3.start()
28     print("end main")
start main
end main
start add1 number= 0.0
number = 1.0
number = 2.0
number = 3.0
number = 4.0
start add3 number= 4.0
number = 7.0
number = 10.0
number = 13.0
number = 16.0