python學習筆記——拾

來源:互聯網
上載者:User

標籤:自己的   效能   進程鎖   判斷   async   技術   狀態   服務   模式   

多進程,進程queue,pipe管道,進程鎖,進程池,協程,5種網路模式(阻塞io,非阻塞io,訊號驅動io,io多工,非同步io)

 

多進程

import multiprocessing 

每個進程都會由他的父進程進行啟動

windows中是pycharm

linux中是 multiprocessing 

獲得進程id

import os
#擷取子進程id
print(os.getppid())
#擷取父進程id
print(os.getpid())

輸出

 

 

進程queue 資料不是共用 

同一個進程中的線程 記憶體是共用的 用之前的線程隊列傳輸資料

但是進程之間記憶體不是共用的,進程之間的資料通訊就用到了

進程queue,它和線程queue不一樣,它是相當於複製了一份在其他進程中。

from multiprocessing import Process, Queue

 

def f(qq):
   #在子進程中給 進程queue添加資料
    qq.put([42, None, ‘hello‘])

if __name__ == ‘__main__‘:
    #在父進程中建立一個進程queue隊列
    q = Queue()
   #建立一個進程對象,進程queue作為參數放入進去
    p = Process(target=f, args=(q,))
   #啟動一個進程
    p.start()
    print(q.get())
    p.join()

 

輸出如下:

 

pipe管道 資料不是共用,只是複製一份

兩個進程之間的通訊 還可以用到管道 pipe 類似於scoket一個發一個收

 

 

 

manager進程資料共用

from multiprocessing import Process, Manager
def f(d, l):
    ‘‘‘此方法用於被進程執行‘‘‘
    d[1] = ‘1‘
    d[‘2‘] = "wwwww"
    l=["A","B"]
    print(l,d)

if __name__ == ‘__main__‘:
    #等於   manager= Manager()
    with Manager() as manager:
        d = manager.dict() #建立一個字典用於進程之間的資料共用
        l = manager.list()#建立一個列表用於進程之間的資料共用
        p_list = [] #為了迴圈join的列表
        for i in range(10):#迴圈10次建立10個進程
            p = Process(target=f, args=(d, l))#建立進程 把字典和列表傳進去
            p.start()
            p_list.append(p)
        for res in p_list:
            res.join()
        print(d)
        print(l)

 

進程鎖

進程鎖存在的目的是為了 多個進程列印資料時不會亂

保證每個進程同一時間單獨佔一塊螢幕

 

 

進程池 

進程池的作用 多進程時機器開銷很大 進程池保證在這段代碼在同一時間

運行進程的個數,避免系統開銷過大而掛掉

線程是沒有線程池的,因為它的開銷很小。需要可以用訊號量自己寫一個

 

 

協程

協程被稱為微線程,是一種使用者級的輕量級線程,擁有自己的寄存器上下文和棧

可以對任務不停的上下切換。並獨立儲存上次離開的位置,避免串列 阻塞 造成的時間浪費,從而大幅度提高效率。

效果類似於多線程,卻又不同

1.在切換時

不管進程或者線程 每次阻塞 切換都需要系統調用,先讓cpu跑作業系統的調用程式,然後再由發送器判斷跑那個 線程或進程

但協程是程式自身控制的,就沒有了線程切換的開銷。和多線程比,線程的數量越多,協程的優勢就越明顯。

2.線程鎖(互斥鎖)

協程因為只有一個線程,所以也不存在同時寫變數衝突,在協程中不需要加鎖,只判斷狀態就好,說以效率比多線程高很多。

利於cpu多核時 可以多進程+協程 充分利用了多核,又發揮了協程的高效率。

 

手動協程 greenlet

 

協程 超級自動版 gevent  最常用

封裝了手動協程(greenlet),在遇到io操作時,會自動切換到下一個方法,當下一個方法遇到io操作時,又切換回去。這就避免了因為等待io執行而造成的時間浪費。

如 線程正常串列遇到io就等待 總共需要3秒,而協程只需要2秒

如果協程方法需要參數,參照如下 f是方法,後邊是參數

 

最簡單的爬取網頁 相當於下載  

利用了協程

 

協程實現socekt

用戶端

服務端

事件驅動型 

現在的ui編程都是事件驅動型的

點擊一個任務,比如開啟一個文本。會把這個事件放入一個隊列中去,

然後有一個線程去處理隊列中的事件。這樣就避免了 滑鼠或者鍵盤引起的阻塞。

 

linux舉例

記憶體空間分為

核心空間 作業系統核心啟動並執行空間

獨立於普通的應用程式 可以訪問底層硬體 受保護的記憶體空間

使用者空間

運行程式啟動並執行空間

核心空間的記憶體 和 使用者空間的記憶體不是共用的

在寫scoket,發送資料時,發現程式不是立刻發送,而是等待緩衝的閾值滿了之後才發送。這是因為 核心空間 需要把資料拷貝到 使用者空間,這些資料拷貝操作所帶來的 CPU 以及記憶體開銷是非常大的,所以才有了緩衝。資料攢多了,一起發送。

一次IO訪問(以read舉例),資料會先被拷貝到作業系統核心的緩衝區中,然後才會從作業系統核心的緩衝區拷貝到應用程式的地址空間。所以說,當一個read操作發生時,它會經曆兩個階段:
1. 等待資料準備 (Waiting for the data to be ready)
2. 將資料從核心拷貝到進程中 (Copying the data from the kernel to the process)

因為以上兩種方式,所以產生了以下5種網路模式

 

阻塞io 單線程下,只能維護一個scoket連結 等待資料和拷貝資料兩個階段都屬於阻塞狀態

 

非阻塞io 單線程下,當使用者進程發出reav操作的時候,如果核心的資料沒有準備好,不會阻塞,而是返回error。

 

訊號驅動io

 

IO多工

特點:在單線程成下,可以迴圈維護多個scoket串連,任意一個資料準備就緒,就會返回給使用者 拷貝資料於阻塞狀態

 

io多工三種模式:

select()幾乎在所有的平台都支援,預設只能維護1024個scoke t。

另外有如果有1000個串連,只有最後一個串連返回資料。那麼會迴圈9999次,很浪費效能。

 

poll()屬於過度階段

 

epoll()不支援windows 支援linux

 nigix 說是非同步io  其實是io多工  epoll模式

有點 如果有1000個串連,有一個串連有資料,核心會告訴哪個串連有資料,使用者直接擷取即可。

非同步io 不會對使用者進程產生阻塞,核心會等待資料準備完成,然後將資料拷貝到使用者記憶體,當這一切都完成之後,核心才會給使用者發送訊號,告訴read操作完成了。沒有任何阻塞。

非同步io用的很少 有個專門的模組asyncio

 

 

 

 

 

 

 

 

 

 

 

 

python學習筆記——拾

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.