其他關(guān)于Python的總結(jié)文章請訪問:http://www.reibang.com/nb/47435944
詳解Python中的多線程、線程鎖户辞、線程變量 - threading泌类、Thread、Lock與ThreadLocal詳解
關(guān)于多進(jìn)程的內(nèi)容請參考:<>
一個進(jìn)程可以包含多個線程底燎,而且至少必須要有一個線程刃榨,這個線程被稱為主線程,在Python中的名字為 MainThread
双仍。進(jìn)程與線程最大的不同在于枢希,進(jìn)程的信息時各自的,而(同一個進(jìn)程下的)線程的信息是公用的朱沃,即他們都處理苞轿、使用所在進(jìn)程的信息數(shù)據(jù)等。
可以使用Python中的threading
模塊進(jìn)行線程管理于操作为流。使用 threading.current_thread()
獲取當(dāng)前所在線程呕屎,使用線程實例的name
屬性獲取線程的名字。
使用Thread創(chuàng)建多線程
一個python運行起來后對應(yīng)著一個進(jìn)程敬察,這個進(jìn)程的的主線程即 MainThread
秀睛,使用Thread
可以創(chuàng)建新的線程,創(chuàng)建時使用參數(shù) target
綁定線程運行的目標(biāo)莲祸,使用 name
參數(shù)為線程定義一個名字蹂安。
Thread
的實例有的常用方法:
-
start
:開始執(zhí)行這個線程 -
join
:等待線程執(zhí)行結(jié)束
一個例子:
import time, random, threading
def print_time():
time.sleep(random.random())
print("I'm thread {}, time now is {}".format(threading.current_thread().name, time.time()))
print("The main thread is {}".format(threading.current_thread().name))
thread1 = threading.Thread(target=print_time, name="New Thread 1")
thread2 = threading.Thread(target=print_time, name="New Thread 2")
thread3 = threading.Thread(target=print_time, name="New Thread 3")
thread1.start()
thread2.start()
thread3.start()
thread1.join()
thread2.join()
thread3.join()
得到的結(jié)果是隨機(jī)的:
The main thread is MainThread
I'm thread New Thread 3, time now is 1607256751.4239407
I'm thread New Thread 1, time now is 1607256751.8748183
I'm thread New Thread 2, time now is 1607256751.9063895
使用鎖Lock修改數(shù)據(jù)
由于(同一個進(jìn)程下的)多個線程使用的是同一套數(shù)據(jù),所以如果多個線程同時訪問一個數(shù)據(jù)就會造成沖突锐帜,解決的方法是使用線程鎖田盈,在某個線程修改這個數(shù)據(jù)的時候,它獲得一把鎖缴阎,只有獲得鎖的這個線程有權(quán)利修改這個數(shù)據(jù)允瞧,等修改完成后再釋放鎖,這樣就可以保證在一個時間只有一個線程修改這個數(shù)據(jù)蛮拔。如果多個線程都想請求得到鎖述暂,他們會排隊獲得。
Python中使用threading.Lock
來完成建炫,一個Lock
實例常用的的方法有:
-
acquire
:請求獲得鎖 -
relaese
:釋放鎖
為例確保一個線程在使用完后一定會釋放鎖畦韭,通常使用try...final...
語句,將釋放鎖的代碼放在finally
塊里肛跌。
一個例子:一個線程要給一個數(shù)據(jù)加一艺配,一個線程要給同一個數(shù)據(jù)減一:
import time, random, threading
number = 0
lock = threading.Lock()
def add_one():
global number
for i in range(20):
lock.acquire()
print("I'm thread {}, I acquired the lock.".format(threading.current_thread().name))
try:
number += 1
finally:
lock.release()
print("I'm thread {}, I realised the lock.".format(threading.current_thread().name))
def minus_one():
global number
for i in range(20):
lock.acquire()
print("I'm thread {}, I acquired the lock.".format(threading.current_thread().name))
try:
number -= 1
finally:
lock.release()
print("I'm thread {}, I realised the lock.".format(threading.current_thread().name))
thread_add = threading.Thread(target=add_one, name="Thread ADD")
thread_minus = threading.Thread(target=minus_one, name="Thread MINUS")
thread_add.start()
thread_minus.start()
thread_add.join()
thread_minus.join()
使用ThreadLocal創(chuàng)建進(jìn)程局部變量
設(shè)想如果有多個線程察郁,它們都要處理自己的一個變量,但是又想進(jìn)行對于該變量的信息交換转唉,這樣的情況下皮钠,可以使用一個全局變量來記錄每個線程的局部變量(比如一個字典),顯然是很麻煩的酝掩,于是可以使用ThreadLocal
來處理線程的局部變量鳞芙。
一個例子:兩個線程都有各自的變量number
import threading
local_variable = threading.local()
def print_number():
number = local_variable.number
print("I'm thread {}, I'm processing my number {}".format(threading.current_thread().name, number))
def set_number(num):
local_variable.number = num
print_number()
thread1 = threading.Thread(target=set_number, args=(1,), name="Thread 1")
thread2 = threading.Thread(target=set_number, args=(2,), name="Thread 2")
thread1.start()
thread2.start()
thread1.join()
thread2.join()
得到的結(jié)果如下:
I'm thread Thread 1, I'm processing my number 1
I'm thread Thread 2, I'm processing my number 2