一、.同步與異步,指結果的返回方式:
同步,是所有的操作都做完,才返回結果。
異步,不用等所有操作都做完,即時返回結果。
二、.多進程與多線程的區別:
1、多線程可以共享全局變量,多進程不能。
2、多線程中,所有子線程的進程號相同;多進程中,不同的子進程進程號不同。
3、線程共享內存空間;進程的內存是獨立的。
4、同一個進程的線程之間可以直接交流;兩個進程想通信,必須通過一個中間代理來實現。
5、創建新線程很簡單;創建新進程需要對其父進程進行一次克隆。
6、一個線程可以控制和操作同一進程裡的其他線程;但是進程只能操作子進程。
7、兩者最大的不同在於:在多進程中,同一個變量,各自有一份拷貝存在於每個進程中,互不影響;而多線程中,所有變量都由所有線程共享。
三、多線程的優勢
進程只有一個,所以分配的CPU資源是一定的,多線程只不過是輪流搶占CPU而已,並不會真正提高處理速度。這意味著,多線程的作用主要在於提高了並發數
Python多線程相當於單核多線程,多線程有兩個好處:CPU並行,IO並行,單核多線程相當於自斷一臂。所以,在Python中,可以使用多線程,但不要指望能有效利用多核。如果一定要通過多線程利用多核,那只能通過C擴展來實現,不過這樣就失去了Python簡單易用的特點。不過,也不用過於擔心,Python雖然不能利用多線程實現多核任務,但可以通過多進程實現多核任務。多個Python進程有各自獨立的GIL鎖,互不影響。
四、進程池的概念:
定義一個池子,在裡面放上固定數量的進程,有需求來了,就拿一個池中的進程來處理任務
等到處理完畢,進程並不關閉,而是將進程再放回進程池中繼續等待任務
如果有很多任務需要執行,池中的進程數量不夠,任務就要等待之前的進程執行任務完畢歸來,拿到空閒進程才能繼續執行。
也就是說,進池中進程的數量是固定的,那麼同一時間最多有固定數量的進程在運行
這樣不會增加操作系統的調度難度,還節省了開關進程的時間,也一定程度上能夠實現並發效果。
代碼:
import time
import multiprocessing
class PrintNumber():
def __init__(self, multi_num):
self.multi_num = multi_num
def run_task(self):
sum_num = 1
for i in range(5):
sum_num = i
time.sleep(1)
print("multi_num = {}, output = {}".format(self.multi_num, sum_num))
return self.multi_num,"ok"
def myCallBack(arg):
print(arg)
if __name__ == "__main__":
#numprocess 要創建的進程數,如果省略,將默認使用cpu_count()的值
#initializer每個工作進程啟動時要執行的可調用對象,默認為None
#initargs傳給initializer的參數組
process_pool = multiprocessing.Pool()
for i in range(3):
a=1
test = PrintNumber(i)
process_pool.apply_async(test.run_task, args=(),callback=myCallBack)
# close是不允許再向進程池中添加任務
# 必須close+join,否則主進程跑完了,子進程還沒完,就會報錯
process_pool.close()
process_pool.join()
print("thread join success!")
輸出:
multi_num = 0, output = 0
multi_num = 1, output = 0
multi_num = 2, output = 0
multi_num = 0, output = 1
multi_num = 2, output = 1
multi_num = 1, output = 1
multi_num = 0, output = 2
multi_num = 2, output = 2
multi_num = 1, output = 2
multi_num = 0, output = 3
multi_num = 2, output = 3multi_num = 1, output = 3
multi_num = 0, output = 4
(0, 'ok')
multi_num = 1, output = 4
multi_num = 2, output = 4
(2, 'ok')
(1, 'ok')
thread join success!
進程池加鎖:
import time
import multiprocessing
def get():
for i in range(3):
time.sleep(1)
print(i)
def task(lock):
lock.acquire() #獲取鎖
get()
lock.release() #釋放鎖
def myCallBack(arg):
print(arg)
if __name__ == "__main__":
#numprocess 要創建的進程數,如果省略,將默認使用cpu_count()的值
#initializer每個工作進程啟動時要執行的可調用對象,默認為None
#initargs傳給initializer的參數組
#進程池的鎖需要使用Manager().Lock()
lock=multiprocessing.Manager().Lock()
process_pool = multiprocessing.Pool()
for i in range(3):
process_pool.apply_async(task, args=(lock,))
# close是不允許再向進程池中添加任務
# 必須close+join,否則主進程跑完了,子進程還沒完,就會報錯
process_pool.close()
process_pool.join()
print("thread join success!")
輸出:
0
1
2
0
1
2
0
1
2
thread join success!