python多进程线程学习_python进程、线程的学习心得
什么是多线程竞争?
线程不是独立的,同一个进程里的线程,线程间的数据是共享的,多线程操作时,容易造成数据的混乱,线程不安全。
如何解决?
互斥锁。
好处:能够保证某段关键代码执行时,只有一个线程操作,保证原子性,避免多线程下的资源竞争。
坏处:性能下降,阻止了多线程的并发执行。致命问题,有可能产生死锁。
解释一下什么是锁,有哪几种锁?
锁是python提供的对线程控制的对象。互斥锁,可重入锁,死锁。
互斥锁:同一时刻只允许一个线程操作,具有排他性和唯一性。比如A、B两个线程,A操作时,B只能等着,A执行完,B才能操作。
可重入锁:有时候在同一个线程中,我们可能会多次请求同一资源(就是,获取同一锁钥匙),俗称锁嵌套。
死锁:互相干等着,都不释放锁,程序无法执行下去。
GIL锁(全局解释器锁):限制多线程的同时执行,同一时间,只有一个线程执行,所以cpython里的多线程其实是伪多线程。python使用协程代替多线程来解决,更轻量级的线程,进程和线程的切换时系统确定的,而协程的切换是由程序员确定的,而模块gevent下切换是遇到耗时操作才会切换的。进程有线程,线程有协程。
什么是线程安全,什么是互斥锁?
作用:保证同一时刻只有一个线程访问一个对象的功能。
由于同一进程的多个线程之间是共享系统资源的,多个线程同时对一个对象进行操作时,一个线程对其进行操作尚未结束cpu时间片切换到另一个线程对其操作,再切换回来时,数据已被修改,导致结果出现错误。此时需要对被操作的对象添加互斥锁,保证每个线程对该对象的操作都能得到正确的结果。
说说下面几个概念:同步,异步,阻塞,非阻塞?
同步:排队,一一执行,一个执行完,才执行下一个。
异步:没有先后顺序,同时执行。
阻塞:程序执行到某段,不往下执行了,卡在那里了。
非阻塞:如果这段卡主了,会执行其他代码。
什么是僵尸进程和孤儿进程?怎么避免僵尸进程?
孤儿进程:父进程退出,子进程还在运行的这些子进程都是孤儿进程,孤儿进程将被init 进程(进
程号为1)所收养,并由init 进程对它们完成状态收集工作。
僵尸进程:在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他, 那么他将变成一个僵尸进程。
避免僵尸进程的方法:
1.fork 两次用孙子进程去完成子进程的任务;
2.用wait()函数使父进程阻塞;
3.使用信号量,在signal handler 中调用waitpid,这样父进程不用阻塞。
常见问题总结:
1. 线程和进程有什么不同?
```python
进程:1>系统进行资源分配和调度的一个独立单元
2>进程间不共享全局变量,需要进行进程间的通信
3>进程在运行过程中为独立的内存单元
线程:1>进程的一个实体,是CPU调度和分派的基本单位
2>同时对一个全局变量进行修改,容易混乱(不一定执行完就换线程)
3>线程依赖进程的存在,线程并发性高,占用资源比进程少
4>多线程共享非全局变量不用加锁
5>多线程到同一个函数里执行,函数里的变量各是各的
```
2. 什么是单任务、多任务程序?
```python
参考:
单任务是指一次只能运行一个程序,不能同时运行多个程序
多任务是指可以同时运行多个程序
```
3. Linux系统是\_\_\_\_任务\_\_\_\_用户的系统?
```python
Linux系统是多任务多用户的系统
```
4. 以单核cpu为例,它是怎样完成多任务的?
```python
轮流切换执行
微观上,在任何一个时刻只有一个程序被执行
但切换速度非常的快,因此在宏观上,看上去多个任务在一起执行一样
```
5. 怎样区分并行和并发?
```python
简单来讲:
并行是指多个cpu同时执行多个任务
并发是指单个cpu轮流切换执行多个任务
```
6. 程序和进程有什么区别?
```python
简而言之,代码没有被运行之前是一个程序,当运行起来后就能成为进程
```
8. 子进程和父进程是什么?
```python
通过进程a产生的进程b,a进程就是父进程,b就是子进程
```
9. getpid、getppid的作用是什么?
```python
getpid 获取当前进程的进程号
getppid 获取当前进程的父进程的进程号
```
10. 创建出来的多个子进程,同时对一个相同名字的全局变量操作时会出错么?为什么?
```python
不会出错
因为进程之间的资源是不共享的,各自拥有各自的一份该变量,操作互不影响
```
12. 创建出来的子进程和父进程到底是谁先执行?为什么?
```python
不确定
因为多任务中,谁先被执行,是由cpu的调度算法来决定的,cpu会保证每个进程都能被平均的执行一段时间,一次你看上去会是随机的
```
14. multiprocessing模块的目的是什么?
```python
使用multiprocessing模块中的Process创建一个子进程
```
15. 怎样用multiprocessing模块中的Process创建一个子进程?请写出基本代码
from multiprocessing import Process
def mission():
for i in range(5):
print(i)
if __name__ == "__main__":
p = Process(target=mission) # 创建进程实例
p.start() # 启动子进程
p.join() # 让父进程等待
16. multiprocessing模块中的Process创建了一个子进程后,怎样让子进程开始执行?
```python
调用start方法
```
18. 如果一个程序需要同时执行多个任务,那么一般会怎么做?
```python
使用多进程或者多线程来实现
```
20. 什么是进程池?有什么用?
```python
进程池就是创建出一定固定数量的进程,去执行多个任务
节约创建进程和销毁进程所消耗的资源和空间
当某个任务被执行完毕后,利用该进程再去执行其他的任务,大大提高效率
```
19. 为了完成多个任务一起执行,可以创建多个子进程来执行任务,那么为什么还要进程池呢?
```python
因为每创建一个进程都会申请内存空间,消耗资源,进程结束又要回收资源
如果反复创建进程,又结束进程,会严重影响性能
进程池的目的就是复用进程,大大提高程序的运行效率
```
21. 什么是进程间通信?
```python
简而言之
进程间的资源是不共享的,因此如果在不同进程间的任务需要相互使用对方的资源或信息
那么就需要在进程之间传递信息、传递资源,这就是进程间通信
```
22. 为什么需要进程间通信?
```python
同上
```
23. multiprocessing模块中Queue怎样发送、取出数据?
```python
q = Queue()
q.put(数据) # 存放数据
q.get() # 取出数据
```
# 关卡二
练习题:1. 使用Process创建1个子进程,让子进程每1秒钟打印1个数字,数字从1开始一直到10,即1.2.3......10
# coding=utf-8
import time
from multiprocessing import Process
# 定义子进程的需要执行的任务 函数
def mission():
#打印1-10
for i in range(1,11):
print(i)
time.sleep(1)
def main():
p = Process(target=mission)
p.start()
p.join()
if __name__ == "__main__":
main()
2. 使用multiprocessing模块中的Queue,完成子进程中将hello传递到父进程中,父进程打印出来
# coding=utf-8
import time
from multiprocessing import Process, Queue
# 定义父进程的需要执行的任务 函数
def parent_mission(que):
data = que.get() # 从队列获取数据打印
print(data)
time.sleep(5)
# 定义子进程的需要执行的任务 函数
def children_mission(que):
data = "hello" # 输入hello就会被父进程拿到
que.put(data) # 往队列添加数据
time.sleep(3)
def main():
q = Queue() # 在父进程中定义队列,实现与子进程通信
p = Process(target=children_mission, args=(q,))
p.start() # 启动子进程 执行任务
parent_mission(q) # 在父进程中 执行任务
p.join()
if __name__ == "__main__":
main()
1. 使用进程池完成如下要求:
* 将/usr/lib/python3.5文件夹下的所有py结尾的文件copy到 桌面上的Test文件夹中
* 用多任务(多进程或者多线程)的方式完成Test文件夹中的所有内容复制
* 新的文件夹的名字为“Test-附件”
* 在复制文件的过程中,实时显示复制的进度
import multiprocessing
import os
import time
import random
def copy_file(queue, file_name,source_folder_name, dest_folder_name):
"""copy文件到指定的路径"""
f_read = open(source_folder_name + "/" + file_name, "rb")
f_write = open(dest_folder_name + "/" + file_name, "wb")
while True:
time.sleep(random.random())
content = f_read.read(1024)
if content:
f_write.write(content)
else:
break
f_read.close()
f_write.close()
# 发送已经拷贝完毕的文件名字
queue.put(file_name)
def main():
# 获取要复制的文件夹
source_folder_name = input("请输入要复制文件夹名字:")
# 整理目标文件夹
dest_folder_name = source_folder_name + "[副本]"
# 创建目标文件夹
try:
os.mkdir(dest_folder_name)
except:
pass # 如果文件夹已经存在,那么创建会失败
# 获取这个文件夹中所有的普通文件名
file_names = os.listdir(source_folder_name)
# 创建Queue
queue = multiprocessing.Manager().Queue()
# 创建进程池
pool = multiprocessing.Pool(3)
for file_name in file_names:
# 向进程池中添加任务
pool.apply_async(copy_file, args=(queue, file_name, source_folder_name, dest_folder_name))
# 主进程显示进度
pool.close()
all_file_num = len(file_names)
while True:
file_name = queue.get()
if file_name in file_names:
file_names.remove(file_name)
copy_rate = (all_file_num-len(file_names))*100/all_file_num
print("\r%.2f...(%s)" % (copy_rate, file_name) + " "*50, end="")
if copy_rate >= 100:
break
print()
if __name__ == "__main__":
main()
什么是多线程竞争?
线程不是独立的,同一个进程里的线程,线程间的数据是共享的,多线程操作时,容易造成数据的混乱,线程不安全。
如何解决?
互斥锁。
好处:能够保证某段关键代码执行时,只有一个线程操作,保证原子性,避免多线程下的资源竞争。
坏处:性能下降,阻止了多线程的并发执行。致命问题,有可能产生死锁。
解释一下什么是锁,有哪几种锁?
锁是python提供的对线程控制的对象。互斥锁,可重入锁,死锁。
互斥锁:同一时刻只允许一个线程操作,具有排他性和唯一性。比如A、B两个线程,A操作时,B只能等着,A执行完,B才能操作。
可重入锁:有时候在同一个线程中,我们可能会多次请求同一资源(就是,获取同一锁钥匙),俗称锁嵌套。
死锁:互相干等着,都不释放锁,程序无法执行下去。
GIL锁(全局解释器锁):限制多线程的同时执行,同一时间,只有一个线程执行,所以cpython里的多线程其实是伪多线程。python使用协程代替多线程来解决,更轻量级的线程,进程和线程的切换时系统确定的,而协程的切换是由程序员确定的,而模块gevent下切换是遇到耗时操作才会切换的。进程有线程,线程有协程。
什么是线程安全,什么是互斥锁?
作用:保证同一时刻只有一个线程访问一个对象的功能。
由于同一进程的多个线程之间是共享系统资源的,多个线程同时对一个对象进行操作时,一个线程对其进行操作尚未结束cpu时间片切换到另一个线程对其操作,再切换回来时,数据已被修改,导致结果出现错误。此时需要对被操作的对象添加互斥锁,保证每个线程对该对象的操作都能得到正确的结果。
说说下面几个概念:同步,异步,阻塞,非阻塞?
同步:排队,一一执行,一个执行完,才执行下一个。
异步:没有先后顺序,同时执行。
阻塞:程序执行到某段,不往下执行了,卡在那里了。
非阻塞:如果这段卡主了,会执行其他代码。
什么是僵尸进程和孤儿进程?怎么避免僵尸进程?
孤儿进程:父进程退出,子进程还在运行的这些子进程都是孤儿进程,孤儿进程将被init 进程(进程号为1)所收养,并由init 进程对它们完成状态收集工作。僵尸进程:在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他, 那么他将变成一个僵尸进程。
避免僵尸进程的方法:1.fork 两次用孙子进程去完成子进程的任务;2.用wait()函数使父进程阻塞;3.使用信号量,在signal handler 中调用waitpid,这样父进程不用阻塞。
常见问题总结:
1. 线程和进程有什么不同? ```python 进程:1>系统进行资源分配和调度的一个独立单元 2>进程间不共享全局变量,需要进行进程间的通信 3>进程在运行过程中为独立的内存单元 线程:1>进程的一个实体,是CPU调度和分派的基本单位 2>同时对一个全局变量进行修改,容易混乱(不一定执行完就换线程) 3>线程依赖进程的存在,线程并发性高,占用资源比进程少 4>多线程共享非全局变量不用加锁 5>多线程到同一个函数里执行,函数里的变量各是各的 ```2. 什么是单任务、多任务程序? ```python 参考: 单任务是指一次只能运行一个程序,不能同时运行多个程序 多任务是指可以同时运行多个程序 ```3. Linux系统是\_\_\_\_任务\_\_\_\_用户的系统? ```python Linux系统是多任务多用户的系统 ```4. 以单核cpu为例,它是怎样完成多任务的? ```python 轮流切换执行 微观上,在任何一个时刻只有一个程序被执行 但切换速度非常的快,因此在宏观上,看上去多个任务在一起执行一样 ```5. 怎样区分并行和并发? ```python 简单来讲: 并行是指多个cpu同时执行多个任务 并发是指单个cpu轮流切换执行多个任务 ```6. 程序和进程有什么区别? ```python 简而言之,代码没有被运行之前是一个程序,当运行起来后就能成为进程 ```8. 子进程和父进程是什么? ```python 通过进程a产生的进程b,a进程就是父进程,b就是子进程 ```9. getpid、getppid的作用是什么? ```python getpid 获取当前进程的进程号 getppid 获取当前进程的父进程的进程号 ```10. 创建出来的多个子进程,同时对一个相同名字的全局变量操作时会出错么?为什么? ```python 不会出错 因为进程之间的资源是不共享的,各自拥有各自的一份该变量,操作互不影响 ```
12. 创建出来的子进程和父进程到底是谁先执行?为什么? ```python 不确定 因为多任务中,谁先被执行,是由cpu的调度算法来决定的,cpu会保证每个进程都能被平均的执行一段时间,一次你看上去会是随机的 ```
14. multiprocessing模块的目的是什么? ```python 使用multiprocessing模块中的Process创建一个子进程 ```15. 怎样用multiprocessing模块中的Process创建一个子进程?请写出基本代码
from multiprocessing import Process
def mission():
for i in range(5):
print(i)
if __name__ == "__main__":
p = Process(target=mission) # 创建进程实例
p.start() # 启动子进程
p.join() # 让父进程等待
16. multiprocessing模块中的Process创建了一个子进程后,怎样让子进程开始执行? ```python 调用start方法 ```
18. 如果一个程序需要同时执行多个任务,那么一般会怎么做? ```python 使用多进程或者多线程来实现 ```
20. 什么是进程池?有什么用? ```python 进程池就是创建出一定固定数量的进程,去执行多个任务 节约创建进程和销毁进程所消耗的资源和空间 当某个任务被执行完毕后,利用该进程再去执行其他的任务,大大提高效率 ```
19. 为了完成多个任务一起执行,可以创建多个子进程来执行任务,那么为什么还要进程池呢? ```python 因为每创建一个进程都会申请内存空间,消耗资源,进程结束又要回收资源 如果反复创建进程,又结束进程,会严重影响性能 进程池的目的就是复用进程,大大提高程序的运行效率 ```
21. 什么是进程间通信? ```python 简而言之 进程间的资源是不共享的,因此如果在不同进程间的任务需要相互使用对方的资源或信息 那么就需要在进程之间传递信息、传递资源,这就是进程间通信 ```
22. 为什么需要进程间通信? ```python 同上 ```
23. multiprocessing模块中Queue怎样发送、取出数据? ```python q = Queue() q.put(数据) # 存放数据 q.get() # 取出数据 ```
# 关卡二
练习题:1. 使用Process创建1个子进程,让子进程每1秒钟打印1个数字,数字从1开始一直到10,即1.2.3......10
# coding=utf-8
import time
from multiprocessing import Process
# 定义子进程的需要执行的任务 函数
def mission():
#打印1-10
for i in range(1,11):
print(i)
time.sleep(1)
def main():
p = Process(target=mission)
p.start()
p.join()
if __name__ == "__main__":
main()
2. 使用multiprocessing模块中的Queue,完成子进程中将hello传递到父进程中,父进程打印出来
# coding=utf-8
import time
from multiprocessing import Process, Queue
# 定义父进程的需要执行的任务 函数
def parent_mission(que):
data = que.get() # 从队列获取数据打印
print(data)
time.sleep(5)
# 定义子进程的需要执行的任务 函数
def children_mission(que):
data = "hello" # 输入hello就会被父进程拿到
que.put(data) # 往队列添加数据
time.sleep(3)
def main():
q = Queue() # 在父进程中定义队列,实现与子进程通信
p = Process(target=children_mission, args=(q,))
p.start() # 启动子进程 执行任务
parent_mission(q) # 在父进程中 执行任务
p.join()
if __name__ == "__main__":
main()
1. 使用进程池完成如下要求: * 将/usr/lib/python3.5文件夹下的所有py结尾的文件copy到 桌面上的Test文件夹中 * 用多任务(多进程或者多线程)的方式完成Test文件夹中的所有内容复制 * 新的文件夹的名字为“Test-附件” * 在复制文件的过程中,实时显示复制的进度
importmultiprocessingimportosimporttimeimportrandomdefcopy_file(queue, file_name,source_folder_name, dest_folder_name):"""copy文件到指定的路径"""f_read= open(source_folder_name + "/" + file_name, "rb")
f_write= open(dest_folder_name + "/" + file_name, "wb")whileTrue:
time.sleep(random.random())
content= f_read.read(1024)ifcontent:
f_write.write(content)else:breakf_read.close()
f_write.close()#发送已经拷贝完毕的文件名字
queue.put(file_name)defmain():#获取要复制的文件夹
source_folder_name = input("请输入要复制文件夹名字:")#整理目标文件夹
dest_folder_name = source_folder_name + "[副本]"
#创建目标文件夹
try:
os.mkdir(dest_folder_name)except:pass #如果文件夹已经存在,那么创建会失败
#获取这个文件夹中所有的普通文件名
file_names =os.listdir(source_folder_name)#创建Queue
queue =multiprocessing.Manager().Queue()#创建进程池
pool = multiprocessing.Pool(3)for file_name infile_names:#向进程池中添加任务
pool.apply_async(copy_file, args=(queue, file_name, source_folder_name, dest_folder_name))#主进程显示进度
pool.close()
all_file_num=len(file_names)whileTrue:
file_name=queue.get()if file_name infile_names:
file_names.remove(file_name)
copy_rate= (all_file_num-len(file_names))*100/all_file_numprint("\r%.2f...(%s)" % (copy_rate, file_name) + " "*50, end="")if copy_rate >= 100:break
print()if __name__ == "__main__":
main()
1 importmultiprocessing2 importos3 importtime4 importrandom5
6
7 defcopy_file(queue, file_name,source_folder_name, dest_folder_name):8 """copy文件到指定的路径"""
9 f_read = open(source_folder_name + "/" + file_name, "rb")10 f_write = open(dest_folder_name + "/" + file_name, "wb")11 whileTrue:12 time.sleep(random.random())13 content = f_read.read(1024)14 ifcontent:15 f_write.write(content)16 else:17 break
18 f_read.close()19 f_write.close()20
21 #发送已经拷贝完毕的文件名字
22 queue.put(file_name)23
24
25 defmain():26 #获取要复制的文件夹
27 source_folder_name = input("请输入要复制文件夹名字:")28
29 #整理目标文件夹
30 dest_folder_name = source_folder_name + "[副本]"
31
32 #创建目标文件夹
33 try:34 os.mkdir(dest_folder_name)35 except:36 pass #如果文件夹已经存在,那么创建会失败
37
38 #获取这个文件夹中所有的普通文件名
39 file_names =os.listdir(source_folder_name)40
41 #创建Queue
42 queue =multiprocessing.Manager().Queue()43
44 #创建进程池
45 pool = multiprocessing.Pool(3)46
47 for file_name infile_names:48 #向进程池中添加任务
49 pool.apply_async(copy_file, args=(queue, file_name, source_folder_name, dest_folder_name))50
51 #主进程显示进度
52 pool.close()53
54 all_file_num =len(file_names)55 whileTrue:56 file_name =queue.get()57 if file_name infile_names:58 file_names.remove(file_name)59
60 copy_rate = (all_file_num-len(file_names))*100/all_file_num61 print("\r%.2f...(%s)" % (copy_rate, file_name) + " "*50, end="")62 if copy_rate >= 100:63 break
64 print()65
66
67 if __name__ == "__main__":68 main()
uma
python多进程线程学习_python进程、线程的学习心得相关推荐
- python的进程和线程定位_Python | 进程 线程的理解拾遗
进程和线程的理解 线程是操作系统能够进行预算调度的最小单位,它包含在进程中是进程中的实际运作单位. Linux 进程有父进程和子进程,window 系统的进程是平等关系 一个标准的线程有线程 ID , ...
- python线程回收_python之线程
开启一个字处理软件进程,该进程肯定需要办不止一件事情,比如监听键盘输入,处理文字,定时自动将文字保存到硬盘,这三个任务操作的都是同一块数据,因而不能用多进程.只能在一个进程里并发地开启三个线程,如果是 ...
- PHP 会话 线程 进程,接上节我们来了解了解多进程的一些基础进程 / 线程 / 多进程 / 父进程 / 子进程 / 会话 / 控制终端等...
多进程的一些基础 定义 进程/父进程/子进程 进程是资源调度和分配的一个独立单元 进程是由线程组成 即等于 一个进程 = 一个线程. 进程是由另一个进程创建 (系统进程 init进程除外) 所以会出现 ...
- python线程退出_python子线程退出及线程退出控制的代码
下面通过代码给大家介绍python子线程退出问题,具体内容如下所示: def thread_func(): while True: #do something #do something #do so ...
- python进程间通信时间开销_python 进程间的通信
python3,进程间的通信 本文来源于python 3.5版本的官方文档 multiprocessing模块为进程间通信提供了两种方法: 1.进程队列queue The Queue class is ...
- python多进程共享内存_python 进程间通信 共享内存
python多进程通信实例分析 python多进程通信实例分析操作系统会为每一个创建的进程分配一个独立的地址空间,不同进程的地址空间是完全隔离的,因此如果不加其他的措施,他们完全感觉不到彼此的存在.那 ...
- python多进程并发代码_Python并发编程系列之多进程(multiprocessing)
1引言 本篇博文主要对Python中并发编程中的多进程相关内容展开详细介绍,Python进程主要在multiprocessing模块中,本博文以multiprocessing种Process类为中心, ...
- python多进程存储数据_Python 多进程及进程间通信
python 因 GIL 的存在,处理计算密集型的任务时无法高效利用多核 CPU 的计算资源,这时就需要使用多进程来提高对 CPU 的资源利用.Python 多进程主要用 multiprocessin ...
- python多进程读写文件_Python多进程写文件时的一些探究
问题提出 在没有并发控制的情况下,Python多进程向同一个文件写数据(限制单次写入数据大小)是安全的吗? 这里的安全是指: 不会有进程的日志丢失(被覆盖) 两次写入的数据不会相互混着输出(譬如A进程 ...
最新文章
- ​70行Go代码打败C
- tightvnc viewer 传文件_TightVNC中文版下载_TightVNC viewer(远程控制软件)简体中文版下载【32位|64位】-华军软件园...
- python怎么用pip_python怎么使用pip工具
- Oracle - 使用各种SQL来熟知buffer cache使用情况
- 机器学习基石13-Hazard of Overfitting
- UVA216 ——dfs
- python对Excel数据进行读写操作
- 将Excel文件数据导入到SqlServer数据库的三种方案
- 将[a=1,b=2] 转为对象
- Windows下免费的屏幕录制软件——EV录屏——推荐
- dcp9020cdn硒鼓!错误_打印机出现硒鼓错误怎么办?打印机显示硒鼓错误分析解决...
- ICCV2021中的时序动作检测算法
- 数据分析案例-气象数据分析
- Mac上如何更改AirDrop名称呢
- matlab画中国地图深浅,matlab绘制中国地图
- TDengine 单节点Cluster not ready( 群集未就绪) 异常问题分析及解决方案
- 2017年05月13日勒索软件, 勒索病毒(WannaCry)肆虐全球, 中国安全防线严重受挫
- 无迹卡尔曼滤波UKF—目标跟踪中的应用(算法部分)
- 计算机发展史之查尔斯·巴贝奇
- 芯片破壁者(三):光刻技术的“鬼斧”之变