進程一

来源:https://www.cnblogs.com/12345huangchun/archive/2018/11/28/10034715.html
-Advertisement-
Play Games

一、什麼是進程 進程(Process)是電腦中的程式關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操作系統結構的基礎。在早期面向進程設計的電腦結構中,進程是程式的基本執行實體;在當代面向線程設計的電腦結構中,進程是線程的容器。程式是指令、數據及其組織形式的描述,進程是程 ...


一、什麼是進程

  進程(Process)是電腦中的程式關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操作系統結構的基礎。在早期面向進程設計的電腦結構中,進程是程式的基本執行實體;在當代面向線程設計的電腦結構中,進程是線程的容器。程式是指令、數據及其組織形式的描述,進程是程式的實體。我們自己在python文件中寫了一些代碼,這叫做程式,運行這個python文件的時候,這叫做進程。

  狹義定義:進程是正在運行的程式的實例(an instance of a computer program that is being executed)。

  廣義定義:進程是一個具有一定獨立功能的程式關於某個數據集合的一次運行活動。它是操作系統動態執行的基本單元,在傳統的操作系統中,進程既是基本的分配單元,也是基本的執行單元   1,進程的概念   第一,進程是一個實體。每一個進程都有它自己的地址空間,一般情況下,包括文本區域(text region)(python的文件)、數據區域(data region)(python文件中定義的一些變數數據)和堆棧(stack region)。文本區域存儲處理器執行的代碼;數據區域存儲變數和進程執行期間使用的動態分配的記憶體;堆棧區域存儲著活動過程調用的指令和本地變數。   第二,進程是一個“執行中的程式”。程式是一個沒有生命的實體,只有處理器賦予程式生命時(操作系統執行之),它才能成為一個活動的實體,我們稱其為進程。進程是操作系統中最基本、重要的概念。是多道程式系統出現後,為了刻畫系統內部出現的動態情況,描述系統內部各道程式的活動規律引進的一個概念,所有多道程式設計操作系統都建立在進程的基礎上。
  2,進程的特征     動態性:進程的實質是程式在多道程式系統中的一次執行過程,進程是動態產生,動態消亡的。     併發性:任何進程都可以同其他進程一起併發執行     獨立性:進程是一個能獨立運行的基本單位,同時也是系統分配資源和調度的獨立單位;     非同步性:由於進程間的相互制約,使進程具有執行的間斷性,即進程按各自獨立的、不可預知的速度向前推進     結構特征:進程由程式、數據和進程式控制制塊三部分組成。     多個不同的進程可以包含相同的程式:一個程式在不同的數據集里就構成不同的進程,能得到不同的結果;但是執行過程中,程式不能發生改變。   註意:同一個程式執行兩次,就會在操作系統中出現兩個進程,所以我們可以同時運行一個軟體,分別做不同的事情也不會混亂

二、併發與並行,同步與非同步

  併發:偽並行,就是幾個進程共用一個cpu,幾個進程之間是時間輪換的,而這個輪換時間很短,肉眼是看不到的,所以我們肉眼看到的是幾個進程同時在進行,其他中間有停止的,只是停止時間短,這就叫併發

  並行:指一個進程就用一個cpu,每個進程是沒有停止的,就是一起運行的

  同步:一個任務執行完後,另一個任務才能開始執行,就是有一個任務需要等待,這樣兩個任務之間的關係是同根生的,非常緊密的

  非同步:兩個任務之間沒有關聯,你執行你的,我執行我的,互相不用等待

三、進程的創建方法

  1,方法一

from multiprocessing import Process            #引入進程模塊,
import os,time
def fun1():
    time.sleep(2)
    print('jjjj')
def fun2():
    time.sleep(3)
    print('ddada')
    print(os.getpid())                #獲得子進程的進程id
    print(os.getppid())                #獲得子進程的父進程,即主進程的id
if __name__=="__main__":            #記住,必須用  if  main 
    start_time=time.time()           #開始時間
    p=Process(target=fun2)             #創建一個子進程
    p.start()                         #開始子進程
    fun1()
    print(os.getpid())               #獲得主進程的進程id
    end_time=time.time()              #結束時間
    print(end_time-start_time)          #列印總共用時
整段程式走完用時2秒多一點,但是如果我們按照以前的寫法,先執行fun1(),再執行fun2(),至少得花5秒

  2,方法二

from multiprocessing import Process       #同樣引入模塊
import time
class Mypro(Process):                 #創建一個類,繼承Process
    def __init__(self,name):
        super().__init__()
        self.name=name
    def run(self):                 #這是必須的方法,然後要執行的程式寫在方法裡面就行
        time.sleep(3)
        print(self.name)
if __name__ == '__main__':        #記住,這裡必須寫 if main
    p1=Mypro('huangchun')         #用自己定義的類創建一個子進程
    p1.start()                    #子進程開始
    p1.join()                    #這是join方法,這樣寫就是join後面的主進程程式必須等子進程執行完後在執行,兩種方法都可以用
    print('我是主進程,哈哈哈哈哈哈。。。。。')

四、守護進程

  把一個子進程設為守護進程之後,每當主進程執行完畢後,不管你子進程有沒有執行完畢,都要跟著結束

from multiprocessing import Process
import time
def fun():
    time.sleep(5)
    print('我是子進程')
if __name__ == '__main__':
    p=Process(target=fun)
    p.daemon = True            #這就是把子進程設為了守護進程,但是切記,這句代碼必須寫在start()前面
    p.start()
    print('我主進程,哈哈哈哈哈哈')
沒有設置守護進程之前,代碼要執行5秒才結束,等到子進程執行完才結束,但是設置為守護進程之後,代碼瞬間執行完畢,只列印了主進程的內容,而子進程的print直接死了

五、同步鎖(互斥鎖)

  對一段程式設置同步鎖之後,不管你對這段程式開了幾個進程,但只有一個進程能執行代碼,而其他的進程需要等待前面的進程結束之後才能執行這段代碼,就相當於把開的幾個進程搞成同步了,互相約束著

這是模擬搶火車票的情景,在還沒付錢確認之前,大家都看見了有一張票,但是只有一個人能搶到票
from
multiprocessing import Process,Lock #引入Lockmok import time def fun1(i): #這是查看餘票的方法 with open('piao.txt',mode='r',encoding='utf-8')as f1: num=f1.read() print('%s客戶看到票還有%s張'%(i,num)) def fun(i,lo): #這是買票的方法 time.sleep(1) lo.acquire() #這是同步鎖的開始, with open('piao.txt',mode='r',encoding='utf-8')as f1: num=f1.read() if num=='1': print('%s買到票了'%i) num=int(num)-1 elif num=='0': print('%s沒票了'%i) with open('piao.txt', mode='w', encoding='utf-8')as f1: f1.write(str(num)) lo.release() 這是同步鎖的結束 if __name__ == '__main__': lo=Lock() #這是創建一把鎖 for i in range(10): #這是迴圈創建10個客戶 fun1(i) #這是客戶查看餘票 p=Process(target=fun,args=(i,lo)) #創建子進程去搶票,然後把鎖傳給進程 p.start()
同步鎖把搶票的程式鎖起來了,所以,雖然有10個客戶都在搶票,但實際上只有一人能進入搶票程式,其他的人要等待第一個進搶票程式的人執行完後才能又進一個人,反正每次就只允許一個人在使用搶票程式,其他的人繼續排隊

六、信號量

  信號量就是對一段程式設定允許最多幾個人使用,相當於一個飯店,只有四個位置,最多允許四個人吃飯,後面人要等待前面的人吃完才能進入飯店吃,前面走一個,就可以進一個

from multiprocessing import Process,Semaphore      #引入Semaphore模塊
import time
def fun(s,i):                    
    s.acquire()
    print('%s客戶在吃'%i)
    time.sleep(1)
    print('%s客戶吃完了'%i)
    time.sleep(1)
    s.release()
if __name__ == '__main__':
    s=Semaphore(4)          #創建信號量對象
    for i in range(10):          #迴圈創建10個人去飯店吃飯
        p=Process(target=fun,args=(s,i)) #創建飯店子進程,然後把信號量傳給子進程
        p.start()

七、事件

  在創建事件之後預設值為False,我們可以把創建的事件對象傳給子進程,然後在子進程中事件對象.set(),使得指變為Ture。然後我們在主進程中加上事件對象.wait(),在此處,只有當值為Ture時不會阻塞,值為False就會阻塞,

從而我們可以用此方法來影響主進程的執行。

from multiprocessing import Process,Event   #引入Event模塊
import time
def func(e):
    print('子進程開始執行')
    time.sleep(3)
    print('子進程結束')
    e.set()                      #設置事件值為Ture,我們還可以通過e.clear()把值改為False
if __name__ == '__main__':
    e=Event()                   #創建事件對象e,此時預設值為False
    p=Process(target=func,args=(e,))       #創建子進程,把e傳給子進程
    p.start()
    print('等待子進程結束後拿到值')
    e.wait()                    #當值為False會阻塞,當值為Ture是,不會阻塞,因為我們在子進程中最好把值改為Ture,所以wait()以後的程式要等到子進程執行完才能執行
    print('拿到值,執行主進程')
    time.sleep(1)
    print('主進程執行完畢')

八、隊列,消費者生產者模型,joinablequeue

  1,隊列

  隊列就相當於一個容器,裡面可以放數據,特點是先放進去先拿出來,即先進先出,

from multiprocessing import Queue       #引入Queue模塊
q=Queue(2)                           #創建一個隊列對象,並給他設置容器大小,即能放幾個數據
q.put(1)                             #put()方法是往容器里放數據
q.put(2)
q.put(3)                             #這是往容器里放第三個數據,由於只能放兩個,所以此處會阻塞,不會報錯,相當於死迴圈
q.put_nowait(4)                      #put_nowait()這也是從容器里放數據的方法,但如果容器滿了,不會阻塞,會直接報錯
q.get()                              #get()方法是從容器里拿數據
q.get()
q.get()                              #這是從容器里拿第三個數據,但是容器的兩個數據拿完了,沒有數據了,此時也會阻塞,不會報錯,死迴圈
q.get(False)                         #這也是從容器里拿數據的方法,當沒數據時不會阻塞,直接報錯
q.get_nowait()                       #這也是從容器里拿數據的方法,當沒數據時不會阻塞,直接報錯
q.full()                             #這是查看容器是否滿了,如果滿了,返回Ture,否則返回False
q.empty()                             #這是查看容器是否為空,如果為空,返回Ture,否則返回False

  2,消費者生產者模型

  就是消費者和生產者之間不是直接聯繫的,而是通過中間的一個隊列來進行聯繫的,生產者把生產的東西放進進隊列里,消費者從隊列里拿東西,其實消費者和生產者之間沒有實質的聯繫

from multiprocessing import Process,Queue
import time
def sheng(q):              #生產者
    for i in range(10):
        time.sleep(1)
        q.put(i)
        print('包子%i生產完畢'%i)
    q.put('over')
def xiao(q):             #消費者
    while 1:
        time.sleep(1.5)
        ss=q.get()
        if ss=='over':
            break
        print('包子%s被吃了'%ss)
if __name__ == '__main__':
    q=Queue(10)           #創建隊列對象q
    p=Process(target=sheng,args=(q,))        #創建生產者子進程,把q傳給他
    p1=Process(target=xiao,args=(q,))        #創建消費者子進程,也把q傳給他
    p.start()
    p1.start()
有個問題就是,生產者要把生產結束的消息放進隊列里,讓消費者過去結束消息,消費者才知道隊列里沒有數據了,這樣消費者才能停止,如果生產者不放結束消息,當生產者結束時,即不往隊列放數據,而消費者不知道生產者已經結束,
還一直往隊列拿數據,當隊列沒數據時,消費者一邊就會阻塞。解決阻塞,有幾個消費者,生產者就應該放幾個結束消息,讓每個消費者都知道,這樣每個消費者才能結束。但是生產者又不知道有幾個消費者,所以不知奧應該放幾個結束數據,
這樣就無法解決對消費者現象。此時,我們就就可以引入joinablequeue

  3,joinablequeue

  他其實就是一種隊列,但她又比隊列要多兩種方法,task_done()和join()方法,正是有這兩種方法就可以解決上面的問題

from multiprocessing import Process,JoinableQueue      #引入joinableQueue模塊
import time
def sheng(q):        #生產者
    for i in range(10):
        time.sleep(1)
        q.put(i)
        print('包子%i生產完畢'%i)
    q.join()                   #當q收到的task_done數量等於放進q的數據數量時,生產者就結束了
def xiao(q,i):                    #消費者
    while 1:
        time.sleep(1.5)
        ss=q.get()
        if ss=='over':
            break
        print('%s客戶吃包子%s'%(i,ss))
        q.task_done()                  #消費者每從q里取一個值,就向q返回一個task_done消息
if __name__ == '__main__':
    q=JoinableQueue()                   #創建joinablequeue對象q
    p=Process(target=sheng,args=(q,))    #創建生產者子進程,把q傳給他
    p.start()
    for i in range(3):                      #迴圈創建消費者子進程,把q傳給他
        p1=Process(target=xiao,args=(q,i))
        p1.daemon=True                   #把創建的每個消費者子進程設為守護進程
        p1.start()
    p.join()                              #主進程要等到生產者子進程結束後才結束
整個個過程就是:生產者生產了10個包子,3個消費者吃包子,沒吃一個包子往q里發一個task_done,當q擁有10個task_done時,意味著10個包子吃完了,此時,生產者就結束了,接著主進程也也結束了,然後守護進程跟著結束了,即所有的消費者子進程結束,解決上面所遇到的問題

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 好記憶不如爛筆頭: ...
  • redis-cachecloud https://github.com/sohutv/cachecloud/wiki/3.%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E6%8E%A5%E5%85%A5%E6%96%87%E6%A1%A3 ...
  • DNS DomainNameSystem功能變數名稱系統,根據功能變數名稱查出IP地址 1.dig命令可以顯示整個查詢的過程 root@VM-38-204-ubuntu:~# dig www.sopans.com //這一段是查詢參數和統計 ; > DiG 9.10.3-P4-Ubuntu > www.sopans... ...
  • """提示:代碼中的內容均被註釋,請參考,切勿照搬""" """註意:代碼切勿照搬,錯誤請留言指出""" ...
  • 題意 "題目鏈接" Sol 一開始的思路:新建一個虛點向每個點連邊,再加上題面中給出的邊,邊權均為大小 需要購買的數量 然後發現死活都過不去 看了題解才發現題目中有個細節——買了$A$就可以買$B$,但是人家沒告訴你必須買夠$A$的數量才能買$B$呀qwqqqqqqq 所以建圖的時候只算一次貢獻就行 ...
  • 這裡有兩張表TableA和TableB,分別是姓名錶和年齡表,用於我們例子的測試數據: 表連接有幾種? sql表連接分成外連接、內連接和交叉連接。 一.外連接 概述: 外連接包括三種,分別是左外連接、右外連接、全外連接。 對應的sql關鍵字:LEFT/RIGHT/FULL OUTER JOIN,通常 ...
  • pip安裝使用 i參數指定源 指定豆瓣源,快如閃電:pip install i http://pypi.douban.com/simple/ 使用sys.modules查看導入包的路徑 sys.modules是一個全局字典,可以通過它來瞭解當前環境載入了什麼包,包的路徑 ...
  • Kibana安裝及使用說明 Kibana是一個針對Elasticsearch的開源分析及可視化平臺,用來搜索、查看交互存儲在Elasticsearch索引中的數據。 官方地址:https://www.elastic.co/cn/products/kibana 一、Kibana安裝 1.環境準備 Ki ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...