什么是多线程竞争?html
线程不是独立的,同一个进程里的线程,线程间的数据是共享的,多线程操做时,容易形成数据的混乱,线程不安全。python
如何解决?程序员
互斥锁。算法
好处:可以保证某段关键代码执行时,只有一个线程操做,保证原子性,避免多线程下的资源竞争。安全
坏处:性能降低,阻止了多线程的并发执行。致命问题,有可能产生死锁。多线程
解释一下什么是锁,有哪几种锁?并发
锁是python提供的对线程控制的对象。互斥锁,可重入锁,死锁。app
互斥锁:同一时刻只容许一个线程操做,具备排他性和惟一性。好比A、B两个线程,A操做时,B只能等着,A执行完,B才能操做。dom
可重入锁:有时候在同一个线程中,咱们可能会屡次请求同一资源(就是,获取同一锁钥匙),俗称锁嵌套。异步
死锁:互相干等着,都不释放锁,程序没法执行下去。
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建立一个子进程?请写出基本代码
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
2. 使用multiprocessing模块中的Queue,完成子进程中将hello传递到父进程中,父进程打印出来
1. 使用进程池完成以下要求:
* 将/usr/lib/python3.5文件夹下的全部py结尾的文件copy到 桌面上的Test文件夹中
* 用多任务(多进程或者多线程)的方式完成Test文件夹中的全部内容复制
* 新的文件夹的名字为“Test-附件”
* 在复制文件的过程当中,实时显示复制的进度
什么是多线程竞争?
线程不是独立的,同一个进程里的线程,线程间的数据是共享的,多线程操做时,容易形成数据的混乱,线程不安全。
如何解决?
互斥锁。
好处:可以保证某段关键代码执行时,只有一个线程操做,保证原子性,避免多线程下的资源竞争。
坏处:性能降低,阻止了多线程的并发执行。致命问题,有可能产生死锁。
解释一下什么是锁,有哪几种锁?
锁是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建立一个子进程?请写出基本代码
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
2. 使用multiprocessing模块中的Queue,完成子进程中将hello传递到父进程中,父进程打印出来
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()