線程
線程基本概念
-
什麼是線程?
瞭解線程之前先說下進程。
進程:一個線程是進程的一個順序執行流,進程是獨立的所有子任務的集合,
線程是應用程序中工作的最小單元。線程:進程中的每個子任務,不能獨立存在
線程,進程:目的都是想同時完成任務
- 各自的特點
- 進程的特點:獨立(內存獨立,cpu使用獨立)啓動進程開銷大(速率低),進程之間很難共享數據,和數據通信,數據安全高。
- 線程的特點:依賴進程(內存共享,CPU使用獨立)啓動開銷小,線程之間共享數據容易,方便通信,線程不安全。
- 各自的特點
-
線程的狀態
創建線程
- Python3 線程中常用的兩個模塊爲:
_thread
threading(推薦使用)
thread 模塊已被廢棄。用戶可以使用 threading 模塊代替。所以,在 Python3 中不能再使用"thread" 模塊。爲了兼容性,Python3 將 thread 重命名爲 “_thread”。 - python中使用線程有兩種方式:函數或用類來包裝線程對象。
- 函數式:調用 _thread 模塊中的start_new_thread()函數來產生新線程。
代碼:
- 函數式:調用 _thread 模塊中的start_new_thread()函數來產生新線程。
import threading
import time
# 爲線程定義一個函數
def someting():
for i in range(1,11):
print(i)
time.sleep(1)
#創建一個函數
threading._start_new_thread(someting(),())
2. 類方式 threading 模塊創建線程
線程模塊同樣提供了Thread類來處理線程,Thread類提供了以下方法:
run(): 用以表示線程活動的方法。
start():啓動線程活動。
join([time]): 等待至線程中止。這阻塞調用線程直至線程的join() 方法被調用中止-正常退出或者拋出未處理的異常-或者是可選的超時發生。
isAlive(): 返回線程是否活動的。
getName(): 返回線程名。
setName(): 設置線程名。
import threading
import time
class Mythread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
print("Mythread")
def run(self):
for i in range(1,11):
print(i)
time.sleep(1)
def start(self):
print("開始Mythread")
super().start()
t=Mythread()
t2 = Mythread()
t.start()
t2.start()
線程同步
使用 Thread 對象的 Lock 和 Rlock 可以實現簡單的線程同步,這兩個對象都有 acquire 方法和 release 方法,對於那些需要每次只允許一個線程操作的數據,可以將其操作放到 acquire 和 release 方法之間。
當多個線程同時進行任務時,爲了保證不會有多個線程同時對同一個數據進行操作造成不可預料的後果,所以有了鎖的概念,我們通過鎖來使多線程任務更加安全。
- 鎖的創建
import threading import time counter = 0 counter_lock = threading.Lock() counter_lock2 = threading.Lock() counter_lock3 = threading.Lock()
可以定義多個鎖, 當你需要獨佔某一資源時,任何一個鎖都可以鎖這個資源
就好比你用不同的鎖都可以把相同的一個門鎖住是一個道理。
import threading
import time
counter = 0
counter_lock = threading.Lock() #只是定義一個鎖,並不是給資源加鎖,你可以定義多個鎖,像下兩行代碼,當你需要佔用這個資源時,任何一個鎖都可以鎖這個資源
counter_lock2 = threading.Lock()
counter_lock3 = threading.Lock()
class MyThread(threading.Thread):
def __init__(self,name):
threading.Thread.__init__(self)
self.name = "Thread-" + str(name)
def run(self): #run函數必須實現
global counter,counter_lock #多線程是共享資源的,使用全局變量
time.sleep(1);
if counter_lock.acquire(): #當需要獨佔counter資源時,必須先鎖定,這個鎖可以是任意的一個鎖,可以使用上邊定義的3個鎖中的任意一個
counter += 1
print ("I am %s, set counter:%s" % (self.name,counter))
counter_lock.release() #使用完counter資源必須要將這個鎖打開,讓其他線程使用
if __name__ == "__main__":
for i in range(1,101):
my_thread = MyThread(i)
my_thread.start()
同一個線程中,RLock.acquire可以被多次調用,利用該特性,可以解決部分死鎖問題。
更多文章:點擊這裏
掃碼關注公衆號《後端開發ipoo》