windows:python
當建立進程時,會將當前py文件由上到下從新執行一次,因此咱們要將執行代碼放在__ main __ 中。linux
linux:程序員
在linux系統中,會直接複製一分代碼去執行windows
這裏有解決問題的辦法:
國內:開源中國,CSDN, cnblods,https://www.v2ex.com/安全
國外:Stack Overflow多線程
GIL: 全局解釋器鎖併發
Cpython的內存管理不是線程安全,在同一進程開啓的多線程,同一時刻只能有一個線程執行,沒法利用多核優點函數
GIL全局解釋鎖,本質上就是一把互斥鎖,保證數據的安全spa
GIL全局解釋器的優缺點:操作系統
1.優勢:
保證數據的安全
2.缺點:
單個進程下,開啓多個線程,犧牲執行效率,沒法實現並行,只能實現併發
,只能實現併發。
IO密集型,多線程
計算密集型,多進程
io密集型任務,每一個任務4s
單核:
開啓的線程比進程節省資源
多核:
多線程:
開啓4個子線程:16s
多進程:
開啓4個進程:16s + 申請開啓資源消耗的時間
計算密集型任務,每一個任務4s
單核:
開啓線程比進程節省資源
多核:
多線程:
開啓4個子線程:16s
多進程:
開啓多個進程:4s
什麼是協程?
進程:資源單位
線程:執行單位
協程: 單線程下實現併發
在io密集的狀況下,使用協程能提升最高效率
ps:協程不是任何單位,只是一個個程序員臆想出來的東西
協成的目的是爲了:
手動實現‘遇到io切換+保存狀態’去欺騙操做系統,讓操做系統誤覺得沒有io操做,將cpu的執行權限給你
from gevent import monkey # 猴子補丁 monkey.patch_all() # 監聽全部的任務是否有io操做 from gevent import spawn # 任務 from gevent import joinall import time def task1(): print('start from task1...') time.sleep(1) print('end from task1...') def task2(): print('start from task2...') time.sleep(2) print('end from task2...') def task3(): print('start from task3...') time.sleep(3) print('end from task3...') if __name__ == '__main__': start_time = time.time() sp1 = spawn(task1) sp2 = spawn(task2) sp3 = spawn(task3) # sp1.start() # sp2.start() # sp3.start() # sp1.join() # sp2.join() # sp3.join() joinall([sp1, sp2, sp3]) end_time = time.time() print(f'消耗時間:{end_time - start_time}') start from task1... start from task2... start from task3... end from task1... end from task2... end from task3... 消耗時間:3.0070078372955322
線程池與進程池中的回調函數的使用: # from gevent import monkey;monkey.patch_all() # from gevent import spawn # import time # # # def task1(name): # print(name) # print('start') # time.sleep(1) # print('end') # # # def task2(): # print('start') # time.sleep(3) # print('end') # # # def task3(): # print('start') # time.sleep(5) # print('end') # # if __name__ == '__main__': # spawn(task1, 'tank') # spawn(task2) # g = spawn(task3) # g.join() # 線程池與進程池 # 進程池 # from concurrent.futures import ProcessPoolExecutor # import time # # 池子對象: 內部能夠幫你提交50個啓動進程的任務 # p_pool = ProcessPoolExecutor(50) # # # def task1(n): # print(f'from task1...{n}') # time.sleep(10) # # # if __name__ == '__main__': # n = 1 # while True: # # 參數1: 函數名 # # 參數2: 函數的參數1 # # 參數3: 函數的參數2 # # submit(參數1, 參數2, 參數3) # p_pool.submit(task1, n) # n += 1 # 線程池 # from concurrent.futures import ThreadPoolExecutor # import time # # 池子對象: 內部能夠幫你提交50個啓動進程的任務 # p_pool = ThreadPoolExecutor(50) # # # def task1(n): # print(f'from task1...{n}') # time.sleep(10) # # # if __name__ == '__main__': # n = 1 # while True: # # 參數1: 函數名 # # 參數2: 函數的參數1 # # 參數3: 函數的參數2 # # submit(參數1, 參數2, 參數3) # p_pool.submit(task1, n) # n += 1 # add_done_callback # from concurrent.futures import ThreadPoolExecutor # import time # # 池子對象: 內部能夠幫你提交50個啓動進程的任務 # p_pool = ThreadPoolExecutor(50) # # # def task1(n): # print(f'from task1...{n}') # time.sleep(5) # return 'tank' # # # def get_result(obj): # # print(obj.__dict__) # # print(obj._result) # result = obj.result() # print(result) # # # if __name__ == '__main__': # n = 1 # while True: # # 參數1: 函數名 # # 參數2: 函數的參數1 # # 參數3: 函數的參數2 # # submit(參數1, 參數2, 參數3) # # add_done_callback(參數1),會將submit提交的task1執行的結果,傳給get_result中的第一個參數,第一個參數是一個對象。 # p_pool.submit(task1, n).add_done_callback(get_result) # n += 1