併發編程前言:python
一、網絡應用程序員
1)爬蟲 直接應用併發編程;django
2)網絡框架 django flask tornado 源碼-併發編程編程
3)socketserver 源碼-併發編程flask
二、運維領域安全
1)自動化開發-運維開發(機器的批量管理,任務的批量執行等)網絡
1、操做系統/應用程序多線程
a、硬件併發
- 硬盤app
- CPU
- 主板
- 顯卡
- 內存
- 電源
. . . . . .
b、裝系統(軟件)
- 系統就是一個由程序員寫出來的軟件,該軟件用於控制計算機的硬件,讓他們之間進行相互配合。
c、安軟件(安裝應用程序)
- 百度雲
- pycharm
. . . . . .
2、並行與併發
併發:是僞並行,即看起來是同時運行。單個cpu+多道技術就能夠實現併發,(並行也屬於併發)
並行:並行:同時運行,只有具有多個cpu才能實現並行
3、線程和進程
a、單進程、單線程的應用程序,好比:
print('666')
b、到底什麼是線程?什麼是進程?
python本身沒有這玩意,python中調用的操做系統的線程和進程。
c、單進程、多線程的應用程序,好比:
import threading print('666') def func(arg): print(arg) t = threading.Thread(target=func,args=(11,)) # 建立一個線程 t.start()
一個應用程序(軟件),能夠有多個進程(默認只有一個),一個進程中能夠建立多個線程(默認一個)。
問題1:爲何有這把GIL鎖?
python語言的創始人在開發這門語言時,目的是快速把語言開發出來,若是加上GIL鎖(c語言加鎖),切換時按照100條字節指令來進行線程間的切換。
問題2:進程和線程的區別?
線程,線程是cpu工做的最小單元;
進程,進程是cpu資源分配的最小單元,爲線程提供一個資源共享的空間;
一個進程中能夠有多個線程,一個進程中默認有一個主線程;
對於python來講,它的進程和線程和其餘語言有差別,有GIL鎖。它保證一個進程中同一時刻只有一個線程被cpu調度;
IO密集型操做可使用多線程,計算密集型可使用多進程;
問題3:線程建立的越多越好嗎?
不是,線程之間進行切換,要作上下文管理。
線程和進程的效率對比:線程的效率很是高,而且線程開啓不須要消耗什麼資源
線程的建立
第一中建立方式:
threading四ruai頂 Thread死ruai的
import time from threading import Thread from multiprocessing import Process def func(n): print(n) if __name__ == '__main__': # t = Thread(target=func,args=('我是線程',)) # t.start() #速度很是快 p = Process(target=func,args=('我是進程',)) p.start() print('主線程結束')
第二種建立方式: 函數繼承Thread
class MyThread(Thread): def run(self): print('sb明傑') if __name__ == '__main__': t = MyThread() t.start() print('主線程結束')
同一進程下,線程是資源共享的
import time from threading import Thread from multiprocessing import Process num = 100 def func(): global num num = 0 if __name__ == '__main__': t = Thread(target=func,) t.start() t.join() print(num)
線程資源共享數據不安全,經過鎖來解決數據不安全的問題,線程模塊裏面引入的鎖
鎖(同步鎖\互斥鎖):保證數據安全,可是犧牲了效率,同步執行鎖內的代碼
import time from threading import Thread,Lock Lock(拉客) num = 100 def func(t_lock): global num # num -= 1 t_lock.acquire() mid = num mid = mid - 1 time.sleep(0.0001) num = mid t_lock.release() if __name__ == '__main__': t_lock = Lock() #鎖對象(同步鎖,互斥鎖) t_list = [] for i in range(10): t = Thread(target=func,args=(t_lock,)) t.start() t_list.append(t) [tt.join() for tt in t_list] print('主線程>>>',num)
解決死鎖線程,用遞歸鎖
互相搶到了對方的須要的鎖,致使雙方相互等待,程序無法進行
import time from threading import Thread,Lock,RLock #遞歸鎖 class MyThread(Thread): def __init__(self,lockA,lockB): super().__init__() self.lockA = lockA self.lockB = lockB def run(self): self.f1() self.f2() def f1(self): self.lockA.acquire() print('我拿了A鎖') self.lockB.acquire() print('我是一個很好的客戶!') self.lockB.release() self.lockA.release() def f2(self): self.lockB.acquire() time.sleep(0.1) print('我拿到了B鎖') self.lockA.acquire() print('我是一名合格的技師') self.lockA.release() self.lockB.release() if __name__ == '__main__': # lockA = Lock() # lockB = Lock() # lockA = lockB = Lock() #不要這麼寫,別本身玩本身,鎖本身 lockA = lockB = RLock() t1 = MyThread(lockA,lockB) t1.start() t2 = MyThread(lockA,lockB) t2.start() print('我是經理')
線程進程效率對比
import time from threading import Thread from multiprocessing import Process def func(n): num = 0 for n1 in range(n): num += n1 print('num',num) if __name__ == '__main__': t_s_t = time.time() t_list = [] for i in range(10): t = Thread(target=func,args=(10,)) t.start() #速度很是快 t_list.append(t) [tt.join() for tt in t_list] t_e_t = time.time() t_dif_t = t_e_t - t_s_t #獲取了線程的執行時間 p_s_t = time.time() #開始時間 p_list = [] for ii in range(10): p = Process(target=func,args=(10,)) p.start() p_list.append(p) [pp.join() for pp in p_list] p_e_t = time.time() #結束時間 p_dif_t = p_e_t - p_s_t #時間差 print('線程>>>>',t_dif_t) print('進程....',p_dif_t) print('主線程結束')
信號量
信號量:控制同時可以進入鎖內去執行代碼的線程數量(進程數量),維護了一個計數器,剛開始建立信號量的時候假如設置的是4個房間,進入一次acquire就加一,出來一次就減一,若是計數器爲0的時候,才能夠繼續搶鑰匙,這樣其餘任務等待,這樣的話,其餘任務都是同步的狀態,而進入acquire裏面去執行的那四個任務是異步執行的
import time from threading import Thread, Semaphore def func1(s): s.acquire() time.sleep(1) print('大寶劍!!!') s.release() if __name__ == '__main__': s = Semaphore(4) for i in range(10): t = Thread(target=func1,args=(s,)) t.start()
主線程等待子線程的緣由
import time from threading import Thread from multiprocessing import Process def func(n): time.sleep(5) print(n) if __name__ == '__main__': # 主線程等待的是子線程的任務所有執行完畢 t = Thread(target=func, args=('我是子線程',)) t.start() # 速度很是快 # 主進程等待的是給子進程收屍 # p = Process(target=func,args=('我是子進程',)) # p.start() # print('主進程結束!!') print('主線程結束')
守護線程
主線程等待全部非守護進程的結束才結束,主線程的代碼運行結束,還要等待守護線的執行完畢,這個過程當中守護線程還存在
守護進程
主進程代碼結束程序並無結束,而且主進程還存在,進程等待其餘的子進程執行結束之後,爲子進程收屍,注意一個問題:主進程的代碼運行結束守護進程跟着結束,
代碼以下
import time from threading import Thread from multiprocessing import Process def func1(n): time.sleep(5) print(n) def func2(n): time.sleep(3) print(n) if __name__ == '__main__': # 進程 p1 = Process(target=func1,args=('我是子進程1號',)) p1.daemon = True #設置守護,在start以前加 p1.start() p2 = Process(target=func2, args=('我是子進程2號',)) p2.start() t1 = Thread(target=func1, args=('我是子xiancheng1號',)) t1.daemon = True t1.start() t2 = Thread(target=func2, args=('我是子xiancheng2號',)) t2.start() print('主進程結束!!') print('主線程結束')
線程的其餘方法 1
from threading import Thread import threading import time from multiprocessing import Process import os def work(): import time time.sleep(1) # print('子線程',threading.get_ident()) #2608 if __name__ == '__main__': #在主進程下開啓線程 t=Thread(target=work) #死如唉的 t.start() current_thread(扣的死如愛的) print(threading.current_thread())#主線程對象 #<_MainThread(MainThread, started 1376)> print(threading.current_thread().getName()) #主線程名稱 #MainThread print(threading.current_thread().ident) #主線程ID #1376 print(threading.get_ident()) #主線程ID #1376 time.sleep(3) print(threading.enumerate()) # 連同主線程在內有兩個運行的線程, enumerate枚舉(額牛木蕊特) print(threading.active_count()) # 2 active_count(啊可特康特) print('主線程/主進程')
事件:
from threading import Thread,Event Event(一溫特) e = Event() #e的狀態有兩種,False True,當事件對象的狀態爲False的時候,wait的地方會阻塞 e.set() #將事件對象的狀態改成True e.clear() #將事件對象的狀態改成Flase clear(克雷爾) print('在這裏等待') e.wait() #阻塞 wait(威特) print('還沒好!!')
線程隊列
隊列有三種模式
先進先出:
import queue q=queue.Queue() q.put('first') # q.put_nowait() #不等待 print(q.get()) q.get_nowait() #沒有數據就報錯,能夠經過try來搞 腦爲特
先進後出:
import queue q=queue.LifoQueue() #隊列,相似於棧,棧咱們提過嗎,是否是先進後出的順序啊 q.put('third') print(q.get())
優先級隊列:
import queue q=queue.PriorityQueue() #put進入一個元組,元組的第一個元素是優先級(一般是數字,也能夠是非數字之間的比較),數字越小優先級越高 q.put((-10,'a')) q.put((-5,'a')) #負數也能夠 q.put((20,'ws')) #若是兩個值的優先級同樣,那麼按照後面的值的acsii碼順序來排序,若是字符串第一個數元素相同,比較第二個元素的acsii碼順序 q.put((20,'wd')) q.put((20,{'a':11})) #TypeError: unorderable types: dict() < dict() 不能是字典 q.put((20,('w',1))) #優先級相同的兩個數據,他們後面的值必須是相同的數據類型才能比較,能夠是元祖,也是經過元素的ascii碼順序來排序 ''' 結果(數字越小優先級越高,優先級高的優先出隊): '''
線程池:
import time from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor from threading import current_thread def func(n): time.sleep(1) # print(n,current_thread().ident) return n**2 if __name__ == '__main__': t_p = ThreadPoolExecutor(max_workers = 4) max_workers(馬克思我K兒死) map_res = t_p.map(func,range(10)) #異步執行的,map自帶join功能 print(map_res) print([i for i in map_res])
回調函數:
import time from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor from threading import current_thread def func(n): time.sleep(1) print(n,current_thread().getName()) return n**2 def func2(n): print('>>>>>>>',n.result()) if __name__ == '__main__': t_p = ThreadPoolExecutor(max_workers = 4) for i in range(3): t_p.submit(func,i).add_done_callback(func2) add_done_callback(俺的 當 考班可) print('主線程結束')
線程池的一些其餘方法:
ThreadPoolExecutor(死日無愛的 噗奧 A克賽K特)
ProcessPoolExecutor(噗賽死 噗奧 A克賽K特)
import time from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor from threading import current_thread def func(n): time.sleep(1) # print(n,current_thread().ident) return n**2 if __name__ == '__main__': t_p = ThreadPoolExecutor(max_workers = 4) t_res_list = [] for i in range(10): res_obj = t_p.submit(func,i)#異步提交了10個任務,submit(色賣特) t_res_list.append(res_obj) t_p.shutdown() #close + join shutdown(莎當) close(可簍子) for e_res in t_res_list: print(e_res.result())#他和get同樣 result(蕊造特)
多線程和多進程進行純計算的效率
import time from multiprocessing import Process from threading import Thread def func(): num = 0 for i in range(1,10000000): num += i # def func(): # time.sleep(2) # print('xxxxxxxx') if __name__ == '__main__': p_s_t = time.time() p_list = [] for i in range(10): p = Process(target=func,) p_list.append(p) p.start() [pp.join() for pp in p_list] p_e_t = time.time() p_dif_t = p_e_t - p_s_t t_s_t = time.time() t_list = [] for i in range(10): t = Thread(target=func,) t_list.append(t) t.start() [tt.join() for tt in t_list] t_e_t = time.time() t_dif_t = t_e_t - t_s_t print('多進程執行的時間',p_dif_t) print('多線程執行的時間',t_dif_t) ''' 多進程執行的時間 4.5982630252838135 多線程執行的時間 8.339477062225342 '''
GIL鎖:
併發執行的效率(在沒有IO的狀況下,兩個純計算的任務 )
import time def func1(): num2 = 0 for i in range(1000001): num2 += i yield # print('執行到下一個yield',current_thread().name) def func2(): g = func1() next(g) sum = 0 for i in range(1000000): # g.send(i) sum += i next(g) s_t = time.time() func2() print('協程的時間',time.time() - s_t)
串行執行的效率
def func1(): num2 = 0 for i in range(1000001): num2 += i # print('執行到下一個yield',current_thread().name) def func2(): sum = 0 for i in range(1000000): sum = sum + i s_t = time.time() func1() func2() print('串行的時間',time.time() - s_t) ''' 協程的時間 0.319796085357666 串行的時間 0.14291739463806152 '''