1. 程式人生 > >總結(3)--- 知識總結(內存管理、線程阻塞、GIL鎖)

總結(3)--- 知識總結(內存管理、線程阻塞、GIL鎖)

操作系統 python2.x 文件 訪問 外觀 python多線程 16px 重新 singleton

一、Python中是如何進行內存管理的?

  • 垃圾回收:Python不像C++,Java等語言一樣,他們可以不用事先聲明變量類型而直接對變量進行賦值。對Python而言,對象的類型和內存都是在運行時確定的。這也是為什麽我們稱Python語言為動態類型的原因
  • 引用計數:Python采用類似Windows內核對象一樣的方式來對內存進行管理。每一個對象都維護這一個對指向該對象的引用的計數。當變量唄綁定在一個對象上的時候,該變量的引用計數就是1,系統會自動維護這些標簽,並定時掃描,當某標簽的引用計數變為0的時候,該對就會被回收
  • 內存池機制Python的內存機制已金字塔行,1,2層主要有操作系統操作
    • 第0層是c中的malloc,free等內存分配和釋放函數進行操作
    • 第1層和第2層是內存池,有Python的接口函數PyMen——Malloc函數實現,當對象小於256K時有該層直接分配內存
    • 第3層是最上層,也就是我們隊Python對象的直接操作
  • 在c中如果頻繁的調用malloc 與 free時, 是會產生性能問題的,再加上頻繁的分配與釋放小塊的內存會產生碎片,Python在這裏主要幹的工作有:
    • 如果請求分配的內存在1~256字節之間就使用字節的內存管理系統,否則直接使用malloc
    • 這裏還是會調用malloc分配內存,但每次會分配一塊大小為256K大塊內存。
    • 經由內存池登記的內存到最後還是會回收到內存池,並不會調用c的free釋放掉。以便下次使用。對於簡單的Python對象,例如數值、字符串,元組采用的是復制的方式,也就是說當將另一個變量B賦值給變量A時,雖然A和B的內存空間仍然相同,但是當A的值發生變化時,會重新給A分配空間,A和B的地址變得不再相同

二、Python中常見的設計模式有哪些?

1. 創建型模式

  • 社會化的分工越來越細,自熱在軟件設計方面也是如此, 因此對象的創建和對象的使用分開也就成為了必然趨勢,因為對象的創建會消耗系統的很多資源,所以單獨對對象的創建進行研究,從而能夠搞笑的創建對象就是創建型模式要探討的問題。這裏有6個具體的創建型模式可供研究,他們分別是:
    • 簡單工廠模式(Simple Factory)
    • 工廠方法模式(Factory Method)
    • 抽象工廠模式(Abstract Factory)
    • 創建者模式(Builder)
    • 原型模式(Prototype)
    • 單例模式(Singleton)

說明:嚴格來說,簡單工廠模式不是GoF總結出來的23種設計模式之一

  • 2、結構型模式
    • 在解決了對象的創建問題之後,對象的組成以及對象之間的依賴關系就成開發人員關註的焦點,因為如何設計對象的結構,繼承和依賴關系會影響到後續程序的維護性、代碼的健壯性、耦合性等。對象結構的設計很容易出現設計人員水平的高低,這裏有7個具體的結構型模式可供研究,他們分別是:
      • 外觀模式(Facade)
      • 適配器模式(Asapter)
      • 代理模式(Proxy)
      • 裝飾模式(Decorator)
      • 橋模式(Bridge)
      • 組合模式(Composite)
      • 享元模式(Flyweight)

  • 3.行為型模式
    • 在對象節後和對象創建問題都解決之後,就剩下對象的行為問題了,如果對象的行為設計的好,那麽對象的行為會更清晰,他們之間的協作效率就會提高,這裏有11個具體的行為型模式可供研究,他們分別是:
      • 模板方法模式(Template Method)
      • 觀察者模式(Observer)
      • 狀態模式(State)
      • 策略模式(Strategy)
      • 職責鏈模式(Chain of Responsibility)
      • 命令模式(Command)
      • 訪問者模式(Visitor)
      • 調停者模式(Mediator)
      • 備忘錄模式(Memento)
      • 叠代器模式(Iterator)
      • 解釋器模式(Interpreter)

三、什麽是線程安全?

線程安全是在多線程的環境下,能夠保證多個線程同時執行時程序依舊運行正確,而且要保證對於共享的數據可以由多個線程存取,但是同一時刻只能有一個線程進行存取。 多線程環境下解決資源競爭問題的辦法是加鎖來保證存取操作的唯一性

四、Gil鎖對Python多線程的影響?

GIL的全稱是Global Interpreter Lock(全局解釋器鎖),來源是Python設計之初的考慮,未來數據安全所做的決定。每個CPU在同一時間只執行一個線程。(在單核CPU下的多線程其實都只是並發,不是並行,並發和並行從宏觀上來講都是同時處理多路請求的概念、 但並發和並行又有區別,並行是指倆個或者多個時間在同一時刻發生;而並發是指倆個或者多個事件在同一時間間隔內發生)

在Python多線程下,每個線程的執行方式:

  1. 獲取GIL
  2. 執行代碼直到sleep或者是Python虛擬機將其掛起
  3. 釋放GIL

可見,某個線程想要執行,必須先拿到GIL,我們可以把GIL看作是"通行證", 並且在一個Python進程中,GIL只用一個,拿不到通行證的線程,就不允許進入CPU執行

在Python2.x裏,GIL的釋放邏輯是當前線程遇見IO操作或者ticks技術達到100 進行釋放,而且每次釋放GIL鎖,線程進行鎖競爭、切換線程,會消耗資源。並且由於GIL鎖存在,Python裏一個進程永遠只能同時執行一個線程(拿到GIL的線程才能執行)

IO密集型代碼(文件處理、網絡爬蟲等) 多線程能夠有效提升效率(單線程下有IO操作會進行IO等待,造成不必要的時間浪費,而開啟多線程能做線程A等待時,自動切換到線程B,可以不浪費CPU資源,從而能提升程序執行效率),所以多線程對IO密集型代碼比較友好

五、什麽是阻塞? 什麽是非阻塞?

阻塞調用時這調用結果返回之前,當前線程會被掛起。函數只有在得到結果之後才會返回。有人也許會把阻塞調用和同步調用等起來,實際上他是不同的。對於同步調用來說,很多時候當前線程還是激活的,只是從邏輯上當前函數沒有返回而已,例如,我們在socket中調用receive函數,如果緩沖區中沒有數據,這個函數就會一直等待,直到有數據才返回。而此時,當前線程還會繼續處理各種各樣的消息,如果主窗口和調用函數在同一個線程中,除非你在特殊的界面操作函數中調用,其實主界面還是應該可以刷新。socket接收數據的另一個函數recv則是一個阻塞調用的例子,當socket工作在阻塞模式的時候,如果沒有數據的情況下調用該函數,則當前線程就會被掛起,直到有數據為止

非阻塞和阻塞的概念相對應,指在不能立刻得到結果之前,該函數不會阻塞當前線程,而會立刻返回

六、軟連接和硬鏈接的區別?

軟連接類似Windows的快捷方式,當刪除源文件,那麽軟連接失效。硬鏈接可以理解為源文件一個別名。多個別名所代表的是一個同一個文件。rm一個文件的時候,那麽此文件的硬鏈接數減一,當硬鏈接數為0的時候,文件刪除

七、單例模式的應用場景有哪些?

單例模式應用的場景一般發現在一下條件下:

(1) 資源共享的情況下,避免由於資源操作時導致性能活損耗等。如日誌文件,應用配置。

(2)控制資源的情況下,方便資源之間的相互通信。如線程池等。

  • 網站的計數器
  • 應用配置
  • 多線程池
  • 數據庫配置,數據庫連接池
  • 應用程序的日誌應用

總結(3)--- 知識總結(內存管理、線程阻塞、GIL鎖)