什麼是多線程競爭?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()