一.并發和并行
-
多任務:一定時間段內,充分利用cpu資源,同時去執行多個任務
-
并發: 快速交替的 去執行多任務
-
并行: 真正同時的 去執行多任務 ,就是同時進行
二.多行程
1.多行程入門
知識點:
-
行程含義: 運行中的程式
-
行程特點: cpu資源分配的 最小單位
-
多行程模塊: multiprocessing
-
行程類: Process
使用步驟:
-
導包 : import multiprocessing
-
創建物件 : 子行程物件 = multiprocessing.Process(target=任務名)
-
開啟行程 : 子行程物件.start()
示例:
import multiprocessing
import time
# 任務1
def dance():
for i in range(5):
time.sleep(0.1)
print('跳舞',i)
# 任務2
def sing():
for i in range(5):
time.sleep(0.3)
print('唱歌',i)
# 多行程放到main內
if __name__ == '__main__':
# 1.創建行程物件
p1 = multiprocessing.Process(target=dance)
p2 = multiprocessing.Process(target=sing)
# 2.開啟行程
p1.start()
p2.start()
2.os模塊獲取行程編號
知識點:
獲取當前行程id: os.getpid() pid: processing id
獲取父行程id: os.getppid() ppid: parent processing id
示例:
import multiprocessing
import os
import time
# 任務1
def dance():
print('dance子行程:', os.getpid(), os.getppid())
for i in range(5):
time.sleep(0.1)
print('跳舞',i)
# 任務2
def sing():
print('sing子行程:', os.getpid(),os.getppid())
for i in range(5):
time.sleep(0.3)
print('唱歌',i)
# 多行程放到main內
if __name__ == '__main__':
print('main主行程:',os.getpid())
# 1.創建行程物件
p1 = multiprocessing.Process(target=dance)
p2 = multiprocessing.Process(target=sing)
# 2.開啟行程
p1.start()
p2.start()
3.Process()類的傳參,2種方式
知識點:
-
args: 以元組方式傳參 注意:如果只有一個引數需要加逗號, 如果多個引數順序要任務引數順序一致
-
kwargs: 以字典方式傳參 注意:需要{k:v}形式傳參,k必須和任務的形參名一致
示例:
import multiprocessing
import os
import time
# 任務1
def dance(num):
print('dance子行程:', os.getpid(), os.getppid())
for i in range(num):
time.sleep(0.1)
print('跳舞',i)
# 任務2
def sing(num):
print('sing子行程:', os.getpid(), os.getppid())
for i in range(num):
time.sleep(0.3)
print('唱歌',i)
# 多行程放到main內
if __name__ == '__main__':
print('main主行程:', os.getpid())
# 1.創建行程物件
p1 = multiprocessing.Process(target=dance,args=(5,))
p2 = multiprocessing.Process(target=sing,kwargs={'num':5})
# 2.開啟行程
p1.start()
p2.start()
4.獲取當前行程資訊
知識點:
-
獲取當前行程物件: multiprocessing.current_process()
-
獲取當前行程name: multiprocessing.current_process().name
-
獲取當前行程pid: multiprocessing.current_process().pid
示例:
import multiprocessing
# 任務1
def dance():
print('dance子行程物件:', multiprocessing.current_process())
print('dance子行程name:', multiprocessing.current_process().name)
print('dance子行程id:', multiprocessing.current_process().pid)
# 任務2
def sing():
print('sing子行程物件:', multiprocessing.current_process())
print('sing子行程name:', multiprocessing.current_process().name)
print('sing子行程id:', multiprocessing.current_process().pid)
# 多行程放到main內
if __name__ == '__main__':
print('main主行程物件:', multiprocessing.current_process())
print('main主行程name:', multiprocessing.current_process().name)
print('main主行程id:', multiprocessing.current_process().pid)
# 1.創建行程物件
p1 = multiprocessing.Process(target=dance,name='danceProcess')
p2 = multiprocessing.Process(target=sing,name='singProcess')
# 2.開啟行程
p1.start()
p2.start()
5.注意事項
1. 多行程間不能共享全域變數:
import multiprocessing
mylist = []
# 寫
def write():
global mylist
mylist = [1,2,3,4,5]
print('write:',mylist) # [1, 2, 3, 4, 5]
# 讀
def read():
global mylist
print('read:',mylist) # [] 說明多個行程間不共享全域變數
# 多行程需要放到main內
if __name__ == '__main__':
# 1.創建行程物件
p1 = multiprocessing.Process(target=write)
p2 = multiprocessing.Process(target=read)
# 2.開啟行程
p1.start()
p2.start()
2. 主行程默認等待子行程結束再結束:
import multiprocessing
import time
# 任務
def task():
for i in range(10):
print('任務進行中...')
time.sleep(0.2)
# 多任務
if __name__ == '__main__':
# 1.創建行程物件
p1 = multiprocessing.Process(target=task)
# 2.開啟行程
p1.start()
# 3.主行程等待0.5秒
time.sleep(0.5)
print('主行程中最后一行代碼....')
2. 主行程默認等待子行程結束再結束:
import multiprocessing
import time
# 任務
def task():
for i in range(10):
print('任務進行中...')
time.sleep(0.2)
# 多任務
if __name__ == '__main__':
# 1.創建行程物件
p1 = multiprocessing.Process(target=task)
# 2.開啟行程
p1.start()
# 3.主行程等待0.5秒
time.sleep(0.5)
print('主行程中最后一行代碼....')
3. 多行程執行是無序的:
import multiprocessing
import time
# 任務
def show():
time.sleep(2)
print(multiprocessing.current_process().name)
# 學習中遇到問題沒人解答?小編創建了一個Python學習交流群:711312441
# 多任務
if __name__ == '__main__':
for _ in range(5):
# 創建行程物件
p = multiprocessing.Process(target=show)
# 開啟行程
p.start()
6.設定子行程跟著主行程一起結束#
知識點:
方式1 設定子行程守護主行程: 子行程物件.daemon = True 注意: 需要在開啟行程之前設定
: daemon/?di?m?n/守護行程
方式2 手動銷毀子行程 : 子行程物件.terminate() terminate:結束,終止
1. 守護主行程:
import multiprocessing
import time
# 任務
def task():
for i in range(10):
print('任務進行中...')
time.sleep(0.2)
# 多任務
if __name__ == '__main__':
# 1.創建行程物件
p1 = multiprocessing.Process(target=task)
# 方式1: 開啟子行程之前設定守護主行程
p1.daemon = True
# 2.開啟行程
p1.start()
# 3.主行程等待0.5秒
time.sleep(0.5)
print('主行程中最后一行代碼....')
2. 手動銷毀子行程:
import multiprocessing
import time
# 任務
def task():
for i in range(10):
print('任務進行中...')
time.sleep(0.2)
# 多任務
if __name__ == '__main__':
# 1.創建行程物件
p1 = multiprocessing.Process(target=task)
# 2.開啟行程
p1.start()
# 3.主行程等待0.5秒
time.sleep(0.5)
print('主行程中最后一行代碼....')
# 方式2: 手動銷毀子行程
p1.terminate()
三.多執行緒
1.多執行緒入門
知識點:
-
執行緒含義: 行程中 執行代碼的 一個分支 (一個行程至少有一個執行緒)
-
執行緒作用: 執行緒是 cpu調度的 最小單位
-
多執行緒模塊: threading
-
執行緒類: Thread
使用步驟:
- 導包 : import threading
- 創建物件 : 子執行緒物件 = threading.Thread(target=任務名)
- 開啟行程 : 子執行緒物件.start()
示例:
import threading
# 任務1
def dance():
for i in range(5):
print('跳舞',i)
# 任務2
def sing():
for i in range(5):
print('唱歌',i)
# 多任務
if __name__ == '__main__':
# 1.創建子執行緒物件
t1 = threading.Thread(target=dance)
t2 = threading.Thread(target=sing)
# 2.開啟執行緒
t1.start()
t2.start()
2.多執行緒的傳參
知識點:
args: 以元組方式傳參 注意:如果只有一個引數需要加逗號, 如果多個引數順序要任務引數順序一致
kwargs: 以字典方式傳參 注意:需要{k:v}形式傳參,k必須和任務的形參名一致
與多行程一模一樣
示例:
import threading
"""
args: 以元組方式傳參 注意:如果只有一個引數需要加逗號, 如果多個引數順序要任務引數順序一致
kwargs: 以字典方式傳參 注意:需要{k:v}形式傳參,k必須和任務的形參名一致
"""
# 任務1
def dance(num):
for i in range(num):
print('跳舞', i)
# 任務2
def sing(num):
for i in range(num):
print('唱歌', i)
# 多任務
if __name__ == '__main__':
# 1.創建子執行緒物件
t1 = threading.Thread(target=dance,args=(5,))
t2 = threading.Thread(target=sing,kwargs={'num':5})
# 2.開啟執行緒
t1.start()
t2.start()
3.多執行緒注意事項
- 多執行緒是在一個行程中
import os
import threading
"""
args: 以元組方式傳參 注意:如果只有一個引數需要加逗號, 如果多個引數順序要任務引數順序一致
kwargs: 以字典方式傳參 注意:需要{k:v}形式傳參,k必須和任務的形參名一致
"""
# 任務1
def dance(num):
print(f'dance子執行緒中當前行程pid:{os.getpid()}')
for i in range(num):
print('跳舞', i)
# 任務2
def sing(num):
print(f'sing子執行緒中當前行程pid:{os.getpid()}')
for i in range(num):
print('唱歌', i)
# 多任務
if __name__ == '__main__':
print(f'main主執行緒中當前行程pid:{os.getpid()}')
# 1.創建子執行緒物件
t1 = threading.Thread(target=dance,args=(5,))
t2 = threading.Thread(target=sing,kwargs={'num':5})
# 2.開啟執行緒
t1.start()
t2.start()
2. 多執行緒是可以共享全域變數
import threading
mylist = []
# 寫
def write():
global mylist
mylist = [1,2,3,4,5]
print('write:',mylist) # [1, 2, 3, 4, 5]
# 讀
def read():
global mylist
print('read:',mylist) # [1, 2, 3, 4, 5] 訪問到了write執行緒修改后的內容說明多執行緒共享全域變數
if __name__ == '__main__':
# 1.創建執行緒物件
t1 = threading.Thread(target=write)
t2 = threading.Thread(target=read)
# 2.開啟執行緒
t1.start()
t2.start()
3. 主執行緒默認等待子執行緒結束再結束
import threading
import time
# 任務
def task():
for i in range(10):
print('任務進行中...')
time.sleep(0.2)
# 多任務
if __name__ == '__main__':
# 1.創建執行緒物件
t = threading.Thread(target=task)
# 2.開啟執行緒
t.start()
# 3.為了效果明顯點,主執行緒等待0.5秒
time.sleep(0.5)
print('主執行緒中最后一行代碼....')
4. 多執行緒是無序的
import threading
import time
# 任務
def show():
time.sleep(1)
print(threading.current_thread().name)
# 多任務
if __name__ == '__main__':
for _ in range(5):
# 創建執行緒物件
p = threading.Thread(target=show)
# 開啟執行緒
p.start()
4.設定守護主執行緒
知識點:
方式1: daemon屬性 t.daemon = True daemon/?di?m?n/守護行程
方式2: setDaemon()方法 t.setDaemon(True)
一個是屬性,一個是方法,用哪個都可以
示例:
import threading
import time
# 任務
def task():
for i in range(10):
print('任務進行中...')
time.sleep(0.2)
# 多任務
if __name__ == '__main__':
# 1.創建執行緒物件
t = threading.Thread(target=task)
# 方式1: daemon屬性
# t.daemon = True
# 方式2: setDaemon()方法
t.setDaemon(True)
# 2.開啟執行緒
t.start()
# 3.為了效果明顯點,主執行緒等待0.5秒
time.sleep(0.5)
print('主執行緒中最后一行代碼....')
5.獲取當前執行緒資訊
知識點:
-
獲取當前執行緒物件:threading.current_thread()
-
獲取當前執行緒name:threading.current_thread().name
-
獲取當前執行緒id:threading.current_thread().native_id
示例:
import threading
def dance():
print(f'dance當前執行緒物件:{threading.current_thread()}')
print(f'dance當前執行緒name:{threading.current_thread().name}')
print(f'dance當前執行緒id:{threading.current_thread().native_id}')
def sing():
print(f'sing當前執行緒物件:{threading.current_thread()}')
print(f'sing當前執行緒name:{threading.current_thread().name}')
print(f'sing當前執行緒id:{threading.current_thread().native_id}')
if __name__ == '__main__':
print(f'main當前執行緒物件:{threading.current_thread()}')
print(f'main當前執行緒name:{threading.current_thread().name}')
print(f'main當前執行緒id:{threading.current_thread().native_id}')
# 1.創建執行緒物件
t1 = threading.Thread(target=dance,name='DanceThread')
t2 = threading.Thread(target=sing,name='SingThread')
# 2.開啟執行緒
t1.start()
t2.start()
6.執行緒安全問題
1. 出現的執行緒安全問題:
import threading
sum = 0
def sum1():
global sum
for i in range(1000000):
sum += 1
print(sum) # 1114834
def sum2():
global sum
for i in range(1000000):
sum += 1
print(sum) # 1339347
# 單任務不會出現問題 正常結果 1000000 2000000
# 多任務出現了問題
if __name__ == '__main__':
# 1.創建執行緒物件
t1 = threading.Thread(target=sum1)
t2 = threading.Thread(target=sum2)
# 2.開啟執行緒
t1.start()
t2.start()
2. 鎖機制解決執行緒安全問題:
import threading
sum = 0
def sum1(lock):
lock.acquire() # 加鎖
global sum
for i in range(1000000):
sum += 1
print(sum) # 1000000
lock.release() # 釋放鎖
def sum2(lock):
lock.acquire() # 加鎖
global sum
for i in range(1000000):
sum += 1
print(sum) # 2000000
lock.release() # 釋放鎖
# 單任務不會出現問題 正常結果 1000000 2000000
# 多任務出現了問題 ,利用鎖機制解決問題
if __name__ == '__main__':
# 創建一個鎖,保證兩個任務用的是同一個鎖
lock= threading.Lock()
# 1.創建執行緒物件
t1 = threading.Thread(target=sum1,args=(lock,))
t2 = threading.Thread(target=sum2,args=(lock,))
# 2.開啟執行緒
t1.start()
t2.start()
3. join解決執行緒安全問題:
import threading
sum = 0
def sum1():
global sum
for i in range(1000000):
sum += 1
print(sum) # 1000000
def sum2():
global sum
for i in range(1000000):
sum += 1
print(sum) # 2000000
# 學習中遇到問題沒人解答?小編創建了一個Python學習交流群:711312441
# 單任務不會出現問題 正常結果 1000000 2000000
# 多任務出現了問題 ,利用join解決問題
if __name__ == '__main__':
# 1.創建執行緒物件
t1 = threading.Thread(target=sum1)
t2 = threading.Thread(target=sum2)
# 2.開啟執行緒
t1.start()
t1.join() # t1執行緒告訴其他執行緒等我執行完,你們其他執行緒再執行
t2.start()
四.行程和執行緒對比
關系
-
執行緒是依附在行程里面的,沒有行程就沒有執行緒
-
一個行程默認提供一條執行緒,行程可以創建多個執行緒
區別
- 行程之間不共享全域變數
- 執行緒之間共享全域變數,但是要注意資源競爭的問題,解決辦法是互斥鎖或者執行緒同步
- 創建行程的資源開銷要比創建執行緒的資源開銷要大
- 行程是作業系統 資源分配 的基本單位,執行緒是 CPU調度 的基本單位
- 執行緒不能夠獨立執行,必須依存在行程中
- 多行程開發比單行程多執行緒開發穩定性要強
優缺點
行程優缺點:
優點:可以用多核
缺點:資源開銷大
執行緒優缺點:
優點:資源開銷小
缺點:不能使用多核
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/544093.html
標籤:其他
下一篇:模擬實作strlen的三種方法
