## 什么是進程
程序并不能單獨運行,只有將程序裝載到內存中,系統為它分配資源才能運行,而這種執行的程序就稱之為進程。程序和進程的區別就在于:程序是指令的集合,它是進程運行的靜態描述文本;進程是程序的一次執行活動,屬于動態概念。在多道編程中,我們允許多個程序同時加載到內存中,在操作系統的調度下,可以實現并發地執行。這是這樣的設計,大大提高了CPU的利用率。進程的出現讓每個用戶感覺到自己獨享CPU,因此,進程就是為了在CPU上實現多道編程而提出的。
## 多道程序設計技術
所謂多道程序設計技術,就是指允許多個程序同時進入內存并運行。即同時把多個程序放入內存,并允許它們交替在CPU中運行,它們共享系統中的各種硬、軟件資源。當一道程序因I/O請求而暫停運行時,CPU便立即轉去運行另一道程序。
## 多進程
實例(可以循環生成多個子進程)
~~~
from multiprocessing import Process
def f(name):
print('hello', name)
if __name__ == '__main__':
p = Process(target=f, args=('bob',)) #生成一個子進程
p.start() #啟動一個子進程
p.join() #等待子進程的執行結束
~~~
## 多進程間的通訊
由于多進程與多線程不同,多線程是處在同一個進程之間,所以多線程之間的內存是共享的,他們可以修改同一個內存中的數據,可以相互之間達到內存共享。但是多進程則不同,多進程之間由于內存獨立,所以數據之間不能直接共享,那么我們如何實現多進程之間的通訊呢?
### 一、Queue隊列
~~~
from multiprocessing import Queue,Process
def func(a):
print('這是子進程:',a.get())
if __name__ == '__main__':
q = Queue()
q.put(123)
p = Process(target=func,args=(q,))
p.start()
運行結果:
>>這是子進程: 123
~~~
進程Queue和線程queue的使用方法基本一致,但是我們在父進程中放入Queue中的數據可以在子進程中拿出(反之也可以),這種方法實現了進程間的數據傳遞。
### 二、**Pipes管道**
~~~
from multiprocessing import Process,Pipe
def func(n):
print(n.recv())
n.send('from son')
if __name__ == '__main__':
f,s = Pipe()
p = Process(target=func,args=(s,))
p.start()
f.send('from father')
print(f.recv())
~~~
實例化管道之后,會返回兩個對象,也就是管道的兩端,將一端留在父進程,一端作為參數傳入給子進程,然后可以通過send和recv方法接收和發送數據,以達到不同進程間的通信。
### 三、**Managers**
~~~
from multiprocessing import Process,Manager
import os
def func(a,b):
a[os.getpid()] = os.getpid()
b.append(os.getpid())
if __name__ == '__main__':
manager = Manager()
d = manager.dict()
l = manager.list()
l2 = []
for i in range(10):
p = Process(target=func,args=(d,l))
p.start()
l2.append(p)
for i in l2:
i.join()
# os.getpid()是獲得當前進程的id,os.getppid()是獲得當前父進程的id
~~~
實例化manager之后。通過manager來生成字典,列表等等,將其傳給子進程,通過這些數據格式來實現不同進程間的通訊。A manager returned by? Manager() will support types?**`list`,?`dict`,?`Namespace`,?`Lock`,?`RLock`,?`Semaphore`,?`BoundedSemaphore`,?`Condition`,?`Event`,?`Barrier`,?`Queue`,?`Value`?and?`Array`.?**
## 進程鎖
```
from multiprocessing import Process, Lock
def f(l, i):
l.acquire()
print('hello world', i)
l.release()
if __name__ == '__main__':
lock = Lock()
for num in range(10):
Process(target=f, args=(lock, num)).start()
進程鎖
```
有人說,線程之間加鎖是為了避免數據混亂,進程之間內存都已經不共享了,為什么還要加鎖呢?如果多個進程同時占有對方需要的資源而同時請求對方的資源,而它們在得到請求之前不會釋放所占有的資源,那么就會導致死鎖的發生,也就是進程不能實現同步。舉個例子就是競爭資源,如當系統中供多個進程共享的資源如打印機、公用隊列等,其數目不足以滿足進程的需要時,會引起諸進程的競爭而產生死鎖。
## 進程池
進程池內部維護一個進程序列,當使用時,則去進程池中獲取一個進程,如果進程池序列中沒有可供使用的進進程,那么程序就會等待,直到進程池中有可用進程為止。
進程池中的方法:
* apply ? ? ? ? ? ? ? ? ? ? ? 從進程池里取一個進程并同步執行? ? ?
* apply\_async ? ? ? ? ? ?從進程池里取出一個進程并異步執行
* terminate? ? ? ? ? ? ? ? ? ? ? ?立刻關閉進程池
* join? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 主進程等待所有子進程執行完畢,必須在close或terminete之后
* close? ? ? ? ? ? ? ? ? ? ? ? ? ? ?等待所有進程結束才關閉線程池
~~~
from multiprocessing import Pool
import time,os
def Foo(i):
time.sleep(2)
print('進程:',os.getpid())
return 'ok' #return的值被回調函數接收
def Bar(arg):
print('-->該子進程執行完畢:', arg,os.getpid()) #由執行結果可以發現回調函數由父進程執行而不由子進程執行
if __name__ == '__main__':
print('父進程:',os.getpid())
pool = Pool(5)
for i in range(10):
pool.apply_async(func=Foo, args=(i,), callback=Bar) #程序異步執行,也就是并行,Bar為回調函數,可以沒有
# pool.apply(func=Foo, args=(i,)) #如果執行這種方法,程序會變成同步執行,也就是串行
pool.close()
pool.join() # 進程池中進程執行完畢后再關閉,如果注釋,那么程序直接關閉。
~~~
```
父進程: 904
進程: 12232
-->exec done: ok 904
進程: 14396
-->exec done: ok 904
進程: 16736
-->exec done: ok 904
進程: 17276
-->exec done: ok 904
進程: 2908
-->exec done: ok 904
進程: 12232
-->exec done: ok 904
進程: 14396
-->exec done: ok 904
進程: 16736
-->exec done: ok 904
進程: 17276
-->exec done: ok 904
進程: 2908
-->exec done: ok 904
執行結果
```
- Python學習
- Python基礎
- Python初識
- 列表生成式,生成器,可迭代對象,迭代器詳解
- Python面向對象
- Python中的單例模式
- Python變量作用域、LEGB、閉包
- Python異常處理
- Python操作正則
- Python中的賦值與深淺拷貝
- Python自定義CLI三方庫
- Python并發編程
- Python之進程
- Python之線程
- Python之協程
- Python并發編程與IO模型
- Python網絡編程
- Python之socket網絡編程
- Django學習
- 反向解析
- Cookie和Session操作
- 文件上傳
- 緩存的配置和使用
- 信號
- FBV&&CBV&&中間件
- Django補充
- 用戶認證
- 分頁
- 自定義搜索組件
- Celery
- 搭建sentry平臺監控
- DRF學習
- drf概述
- Flask學習
- 項目拆分
- 三方模塊使用
- 爬蟲學習
- Http和Https區別
- 請求相關庫
- 解析相關庫
- 常見面試題
- 面試題
- 面試題解析
- 網絡原理
- 計算機網絡知識簡單介紹
- 詳解TCP三次握手、四次揮手及11種狀態
- 消息隊列和數據庫
- 消息隊列之RabbitMQ
- 數據庫之Redis
- 數據庫之初識MySQL
- 數據庫之MySQL進階
- 數據庫之MySQL補充
- 數據庫之Python操作MySQL
- Kafka常用命令
- Linux學習
- Linux基礎命令
- Git
- Git介紹
- Git基本配置及理論
- Git常用命令
- Docker
- Docker基本使用
- Docker常用命令
- Docker容器數據卷
- Dockerfile
- Docker網絡原理
- docker-compose
- Docker Swarm
- HTML
- CSS
- JS
- VUE