[TOC]
### 背景介紹
#### 并發和并行
程序同一進程中線程在一顆CPU上`交替執行`,這樣可以實現`并發`。
程序的不同進程分別在多核CPU上`同時執行`,這樣可以實現`并行`。
### 什么是進程?
計算機程序只不過是磁盤中可執行的,二進制(或其它類型)的數據。它們只有在被讀取到內存中,被操作系統調用的時候才開始它們的生命期。進程(有時被稱為`重量級進程`)是程序的一次執行。每個進程都有自己的`地址空間`,`內存`,`數據棧`以及其它記錄其運行軌跡的`輔助數據`。操作系統管理在其上運行的所有進程,并為這些進程`公平`地分配時間。
進程也可以通過fork或者spawn派生新的進程來執行任務,每個進程都有自己的內存空間和數據棧,所以只能采取`進程間通信`(IPC)共享信息。
>* 進程間公平的分配時間片
>* 進程間不能共享內存
### 什么是線程?
線程(有時被稱為`輕量級進程`)跟進程有些相似,不同的是,所有的線程運行在同一個進程中,共享相同的運行環境。我們可以想像成是在主進程或“主線程”中并行運行的“迷你進程”。
>* 線程間不公平的分配時間片
>* 線程間能共享內存,交換數據
>* 線程是CPU執行的最小單元
### 為什么要使用線程?
大多數的應用程序如果在開發時考慮采用兩個以上線程,那么一般情況下是為每個線程分配了獨立的功能,且這些功能能夠`“并發地"`執行。
點對點的聊天工具,需要在我們編寫信息的同時能夠接受并打印出來對方說的話。如果將信息的發送和接受放在一個線程里,線程的單一順序控制流程特性就使得發送和接受兩者不能兼顧。其實說到“并發地”,實際上,這兩個線程并不是同時在執行,而是`相斥`地,但是由于計算機的數據處理能力很強大,能夠把系統資源快速地在這兩者之間進行調配(切換),以至于我們人感覺不到這個切換的過程,好像它是在并發地執行,也就是說計算機通過多線程提供的所謂“并發性”滿足了程序使用者對于并發性的要求。
### 什么時候使用多線程,什么時候使用多進程?
在python的原始解釋器CPython中存在著GIL(`Global Interpreter Lock`,全局解釋器鎖),因此在解釋執行python代碼時,會產生互斥鎖來限制線程對共享資源的訪問,直到解釋器遇到`I/O操作`或者`操作次數`達到一定數目時才會釋放GIL。所以,雖然CPython的線程庫直接封裝了系統的原生線程,但CPython整體作為一個進程,同一時間只會有一個獲得GIL的線程在跑,其他線程則處于等待狀態。這就造成了即使在多核CPU中,多線程也只是做著分時切換而已。
因為Python的多線程不能調用多個核心,只能利用一個核心. 如果是IO密集帶阻塞的任務,Python的多線程還是很不錯的. 如果是CPU密集, 試試多進程好了。
#### GIL的作用
在執行一些sleep/read/write/recv/send這些會導致阻塞的函數時,當前線程會主動放棄GIL,然后調用相應的系統API,完成后再重新申請GIL。因此,GIL也并不是導致Python的多線程完全沒用,在一些IO等待的場合,Python多線程還是發揮了作用,當然如果多線程都是用于CPU密集的代碼,那多線程的執行效率就明顯會比單線程的低。
### 鎖 線程的通關文牒
當線程遇到需要獲取鎖的時候,能獲取則通過,獲取不到則阻塞在那里,直到獲取鎖或者一直獲取不到;如果在西游中,鎖就像是通關文牒,能拿到則通過,拿不到則通不過。
### 阻塞
阻塞是卡在無法繼續運行后續的代碼。被阻塞的線程是沒有順序的,并不是先到先到先執行,勝出的線程是不確定的。
- 前言
- 環境搭建
- pypi
- 打包
- Python 2 和 Python 3 的版本之間差別
- 項目
- 第一部分
- 第1章 基礎
- Python安裝
- python代碼文件類型
- python對象
- 核心數據類型
- 核心數據類型--整型和浮點型
- 核心數據類型--字符串
- str.format
- 核心數據類型--列表
- 核心數據類型--元組
- 核心數據類型--字典
- 核心數據類型--集合
- 核心數據類型--文件對象
- 調用bash
- 標準輸入輸出
- str-repr
- 字符編碼
- 迭代器和生成器
- 第2章 語句和語法
- 賦值語句
- if語句
- while語句
- for語句
- assert
- 第3章 函數
- 函數作用域
- 工廠函數
- 內置函數
- 遞歸
- 嵌套作用域和lambda
- 參數傳遞
- 函數式編程
- property可寫與可讀
- 第5章 模塊
- 模塊導入
- 模塊命名空間
- 相對導入和絕對導入
- 模塊重載
- 在模塊中隱藏數據
- 過渡性重載
- 第6章 類
- 面向對象還是面向過程?
- 構造函數 析構函數
- call
- 運算符重載
- str()
- 待定
- 即時生成屬性
- 多態
- 線程和進程
- thread模塊
- threading模塊
- threading線程鎖
- 糖果機
- multiprocessing
- 阻塞非阻塞同步異步
- 單線程和多線程對比
- 生產者消費者模型
- 第二部分
- 獲取系統資源信息
- 獲取進程所占的物理內存
- dmidecode獲取系統信息
- 網絡編程
- 網絡基礎
- python中的套接字
- socket模塊
- 第三部分 高級功能
- 閉包入門
- 閉包的應用
- 裝飾器入門
- 裝飾器應用
- 第四部分 項目實戰
- graphite
- 模塊
- collections
- datetime
- Enum
- faker
- fabric
- fileinput
- fire
- fnmatch
- getpass
- glob
- hashlib
- heapq
- json模塊
- log
- os
- Paramiko
- parser
- platform
- pyyaml
- Queue
- random
- re
- 特殊符號和字符
- re模塊
- shelves
- subprocess
- time
- urllib_urllib2_requests
- urllib urllib2
- requests
- 標準模塊ConfigParser
- 擴展模塊Mysqldb
- 擴展模塊dns
- 擴展模塊request
- uuid
- cacheout 緩存庫
- delorean 時間
- 附錄
- 內置函數
- python實現各種排序算法
- 常見報錯
- pymongo
- pyrocksdb
- 常用
- ERROR