linux查看python线程,Python多线程详解
線程概念:
線程是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以并發多個線程,每條線程并行執行不同的任務。線程可以分為兩類:
內核線程:由操作系統內核創建和撤銷。
用戶線程:不需要內核支持而在用戶程序中實現的線程。
全局解釋性鎖(GIL):
在講Python多線程,有一個繞不開的東西,叫全局解釋性鎖(Global Interpreter Lock)。這東西導致了無論你啟多少個線程,你有多少個cpu, Python在執行的時候同一時刻只允許一個線程運行。這就導致了大家對Python多線程的印象普遍就是‘雞肋“。
需要注意的一點是GIL并不是Python的特性,它是在實現Python解析器(CPython)時所引入的一個概念。就好比C++是一套語言(語法)標準,但是可以用不同的編譯器來編譯成可執行代碼。有名的編譯器例如GCC,INTEL C++,Visual C++等。Python也一樣,同樣一段代碼可以通過CPython,PyPy,Psyco等不同的Python執行環境來執行。像其中的JPython就沒有GIL。然而因為CPython是大部分環境下默認的Python執行環境。所以在很多人的概念里CPython就是Python,也就想當然的把GIL歸結為Python語言的缺陷。所以這里要先明確一點:GIL并不是Python的特性,Python完全可以不依賴于GIL。
線程模塊:
Python3 通過兩個標準庫 _thread 和 threading 提供對線程的支持。_thread 提供了低級別的、原始的線程以及一個簡單的鎖,它相比于 threading 模塊的功能還是比較有限的。threading 模塊除了包含 _thread 模塊中的所有方法外,還提供的其他方法:
threading.currentThread(): 返回當前的線程變量。
threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啟動后、結束前,不包括啟動前和終止后的線程。
threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。
除了使用方法外,線程模塊同樣提供了Thread類來處理線程,Thread類提供了以下方法:
run(): 用以表示線程活動的方法。
start():啟動線程活動。
join([time]): 等待至線程中止。這阻塞調用線程直至線程的join() 方法被調用中止-正常退出或者拋出未處理的異常-或者是可選的超時發生。
isAlive(): 返回線程是否活動的。
getName(): 返回線程名。
setName(): 設置線程名。
Python threading模塊:
(1)線程創建方式一:直接調用線程,創建Thread類,并傳遞一個需要多線程運行的函數。示例如下:
import threading
import time
def func(no):
time.sleep(2)
print("the thread number:%s"%no)
time_start = time.time()
thread_list = []
for i in range(10):
t = threading.Thread(target=func,args=(i,))? #生成線程實例
t.start()? #啟動線程
thread_list.append(t)
for t in thread_list:
t.join()? #等待線程中止
time_end = time.time()
print("程序總共運行%d秒"%int(time_end-time_start))
#運行結果:
the thread number:4
the thread number:2
the thread number:5
the thread number:1
the thread number:3
the thread number:0
the thread number:7
the thread number:9
the thread number:6
the thread number:8
程序總共運行2秒
(2)線程創建方式二:繼承式調用,創建一個Thread類的子類,并重寫Thread類的run方法。示例如下:
import threading
import time
class TestThread(threading.Thread):
def __init__(self,no):
threading.Thread.__init__(self)
self.no = no
def run(self):? #重寫父類Thread的run方法,改方法內定義每個線程要運行的程序代碼
time.sleep(2)
print("the thread number:%s" % self.no)
for i in range(10):
t = TestThread(i)
t.start()
(3)守護進程:
import threading
import time
def run(i):
print("run({}) start".format(i))
time.sleep(2)
print("run({}) end".format(i))
def main():
for i in range(5):
t = threading.Thread(target=run,args=(i,))
t.start()
m = threading.Thread(target=main,args=())
m.setDaemon(False)
m.start()
m.join(timeout=1)
print("main thread end")
# m.setDaemon(True) 運行結果:
run(0) start
run(1) start
run(2) start
run(3) start
run(4) start
main thread end
# m.setDaemon(False) 運行結果:
run(0) start
run(1) start
run(2) start
run(3) start
run(4) start
main thread end
run(3) end
run(2) end
run(0) end
run(4) end
run(1) end
從上述示例中可以看出:將main線程設置為Daemon線程,它做為程序主線程的守護線程,當主線程退出時,m線程也會退出,由m啟動的其它子線程會同時退出,不管是否執行完任務
(4)線程同步(線程鎖):一個進程下可以啟動多個線程,多個線程共享父進程的內存空間,也就意味著每個線程可以訪問同一份數據,很容易造成數據不同步。使用 Thread 對象的 Lock 和 Rlock 可以實現簡單的線程同步,這兩個對象都有 acquire 方法和 release 方法,對于那些需要每次只允許一個線程操作的數據,可以將其操作放到 acquire 和 release 方法之間。示例如下:
import threading
import time
def add():
global num? #獲取全局變量
time.sleep(1)
Lock.acquire()? #修改全局變量前獲取鎖(加鎖)
num -= 1
Lock.release()? #修改后釋放鎖
Lock = threading.Lock()? #生成一個全局鎖
num = 100? #設置一個共享數據
thread_list = []
for i in range(100):
t = threading.Thread(target=add,args=())
t.start()
thread_list.append(t)
for t in thread_list:
t.join()
print("final num:",num)
#運行結果:
在未加鎖前結果不一定是 0
加鎖后運行結果一定是 0
總結
以上是生活随笔為你收集整理的linux查看python线程,Python多线程详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实施工程师常用linux命令,009Li
- 下一篇: linux语言windows 语言,作业