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