Python day 34 并发编程、PID/PPID、实现多进程得两种方式
生活随笔
收集整理的這篇文章主要介紹了
Python day 34 并发编程、PID/PPID、实现多进程得两种方式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
## 進程及并發的產生
```python
進程指的是正在運行的程序,是一系列過程的統稱,也是操作系統在調度和進行資源分配的基本單位
并發,指的是多個任務同時被執行,并發編程指的是編寫支持多任務并發的應用程序在。(看似同時執行,因為cpu得任務切換很快)
'并行:是真正意義上的多任務同時被執行。
'進程這個概念來自于操作系統,沒有操作系統就沒有進程
# 操作系統的兩個核心作用
1.為用戶屏蔽了復雜繁瑣的硬件接口,為應用程序提供了,清晰易用的系統接口
有了這些接口以后程序員不用再直接與硬件打交道了
2.操作系統將應用程序對硬件資源的競爭變成有序的使用
# 操作系統與應用程序的區別
二者的區別不在于的地位,它們都是軟件,而操作系統可以看做一款特殊的軟件
1.操作系統是是受保護的:無法被用戶修改(應用軟件如qq不屬于操作系統可以隨便卸載)
2.大型:linux或widows源代碼都在五百萬行以上,這僅僅是內核,不包括用戶程序,如GUI,庫以及基本應用軟件(如windows Explorer等),很容易就能達到這個數量的10倍或者20倍之多
3.長壽:由于操作系統源碼量巨大,編寫是非常耗時耗力的,一旦完成,操作系統所有者便不會輕易的放棄重寫,二是在原有基礎上改進,基本上可以把windows95/98/Me看出一個操作系統
第三代計算機產生了多道技術
多進程實現得原理:多道技術
多道技術:1,空間上得復用
2,時間上的復用
```
## PID禾PPID
```python
# PID
在一個操作系統中通常都會運行多個應用程序,也就是多個進程,那么如何來區分進程呢?
系統會給每一個進程分配一個進程編號即PID,如同人需要一個身份證號來區分。
驗證:
tasklist 用于查看所有的進程信息
taskkill /f /pid pid 該命令可以用于結束指定進程
# 在python中可以使用os模塊來獲取pid
import os
print(os.getpid())
# PPID
當一個進程a開啟了另一個進程b時,a稱為b的父進程,b稱為a的子進程
在python中可以通過os模塊來獲取父進程的pid
# 在python中可以使用os模塊來獲取ppid
import os
print("self",os.getpid()) # 當前進程自己的pid
print("parent",os.getppid()) # 當前進程的父進程的pid
如果是在pycharm中運行的py文件,那pycahrm就是這個python.exe的父進程,當然你可以從cmd中來運行py文件,那此時cmd就是python.exe的父進程
```
## 阻塞與非阻塞
```python
# 阻塞與非阻塞指的是程序的狀態
阻塞狀態是因為程序遇到了IO操作,或是sleep,導致后續的代碼不能被CPU執行
非阻塞與之相反,表示程序正在正常被CPU執行
補充:進程有三種狀態
就緒態,運行態,和阻塞態
多道技術會在進程執行時間過長或遇到IO時自動切換其他進程,意味著IO操作與進程被剝奪CPU執行權都會造成進程無法繼續執行
```
## python中實現多進程的兩種方式
### 方式1:
### 實例化Process類
```python
from multiprocessing import Process
import time
def task(name):
print('%s is running' %name)
time.sleep(3)
print('%s is done' %name)
if __name__ == '__main__':
# 在windows系統之上,開啟子進程的操作一定要放到這下面
# Process(target=task,kwargs={'name':'egon'})
p=Process(target=task,args=('jack',))
p.start() # 向操作系統發送請求,操作系統會申請內存空間,然后把父進程的數據拷貝給子進程,作為子進程的初始狀態
print('======主')
```
### 方式2:
### 繼承Process類 并覆蓋run方法
```python
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,name):
super(MyProcess,self).__init__()
self.name=name
def run(self):
print('%s is running' %self.name)
time.sleep(3)
print('%s is done' %self.name)
if __name__ == '__main__':
p=MyProcess('jack')
p.start()
print('主')
```
需要注意的是
1.在windows下 開啟子進程必須放到`__main__`下面,因為windows在開啟子進程時會重新加載所有的代碼造成遞歸創建進程(發生了導入)
2.第二種方式中,必須將要執行的代碼放到run方法中,子進程只會執行run方法其他的一概不管
### join函數
調用start函數后的操作就由操作系統來玩了,至于何時開啟進程,進程何時執行,何時結束都與應用程序無關,所以當前進程會繼續往下執行,join函數就可以是父進程等待子進程結束后繼續執行
案例
```python
from multiprocessing import Process
import time
x=1000
def task():
time.sleep(3)
global x
x=0
print('兒子死啦',x)
if __name__ == '__main__':
p=Process(target=task)
p.start()
p.join() # 讓父親在原地等
print(x)
```
## Process對象常用屬性
```PYTHON
from multiprocessing import Process
def task(n):
print('%s is runing' %n)
time.sleep(n)
if __name__ == '__main__':
start_time=time.time()
p1=Process(target=task,args=(1,),name='任務1')
p1.start() # 啟動進程
print(p1.pid) # 獲取進程pid
print(p1.name) # 獲取進程名字
p1.terminate() # 終止進程
p1.join() # 提高優先級
print(p1.is_alive()) # 獲取進程的存活狀態
print('主')
```
# 孤兒進程與僵尸進程(了解)
#### 什么是孤兒進程
孤兒進程指的是開啟子進程后,父進程先于子進程終止了,那這個子進程就稱之為孤兒進程
例如:qq聊天中別人發給你一個鏈接,點擊后打開了瀏覽器,那qq就是瀏覽器的父進程,然后退出qq,此時瀏覽器就成了孤兒進程
孤兒進程是無害的,有其存在的必要性,在父進程結束后,其子進程會被操作系統接管。
#### 什么是僵尸進程
僵尸進程指的是,當子進程比父進程先結束,而父進程又沒有回收子進程,釋放子進程占用的資源,此時子進程將成為一個僵尸進程。如果父進程先退出 ,子進程被操作系統接管,子進程退出后操作系統會回收其占用的相關資源!
#### 僵尸進程的危害:
由于子進程的結束和父進程的運行是一個異步過程,即父進程永遠無法預測子進程 到底什么時候結束. 那么會不會因為父進程太忙來不及wait子進程,或者說不知道 子進程什么時候結束,而丟失子進程結束時的狀態信息呢? 不會。因為UNⅨ提供了一種機制可以保證只要父進程想知道子進程結束時的狀態信息, 就必然可以得到。這種機制就是: 在每個進程退出的時候,內核釋放該進程所有的資源,包括打開的文件,占用的內存等。但是仍然為其保留一定的信息(包括進程號the process ID,退出狀態the termination status of the process,運行時間the amount of CPU time taken by the process等)。直到父進程通過wait / waitpid來取時才釋放. 但這樣就導致了問題,如果進程不調用wait / waitpid的話,那么保留的那段信息就不會釋放,其進程號就會一直被占用,但是系統所能使用的進程號是有限的,如果大量的產生[僵死進程],將因為沒有可用的進程號而導致系統不能產生新的進程. 此為僵尸進程的危害,應當避免。
總結
以上是生活随笔為你收集整理的Python day 34 并发编程、PID/PPID、实现多进程得两种方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SmartLink
- 下一篇: Redis之ZSet命令