Python中的多執行緒與佇列

2021-08-20 19:45:25 字數 2453 閱讀 9975

0x01 執行緒鎖

既然說到多執行緒,就會經常遇到多個執行緒共同操作乙個單元或空間的情況,對該單元進行修改、獲取等操作,為了避免各執行緒間的混亂操作,保證執行緒同步的正確性,很有必要引入執行緒鎖的概念。

執行緒鎖,顧名思義,表示某一單元或空間只為某一線程所有,此時其他執行緒均無法進行操作,等待該執行緒操作完成並釋放鎖之後,其他執行緒才可繼續利用該單元。

python中線程鎖的用法很簡單,使用thread物件中的lock方法即可,在需要加鎖的地方呼叫accquire方法,之後呼叫release方法釋放鎖。

import threading

th_lock = threading.lock()

th_lock.accquire()

#加鎖內容

...#th_lock.release()

用法非常簡單,但在真實開發中,鎖使用的位置卻非常關鍵,它需要你考慮到你所操作單元的當前狀態是否可能被其他執行緒修改獲取等,又要考慮工作效率的最大化。

0x02 多執行緒與佇列

我們經常會遇到這樣的乙個問題,這裡有成千上萬條資料,每次需要取出其中的一條資料進行處理,那麼引入多執行緒該怎麼進行任務分配?

我們可以將資料進行分割然後交給多個執行緒去跑,可是這並不是乙個明智的做法。在這裡我們可以使用佇列與執行緒相結合的方式進行任務分配。

佇列執行緒的思想: 首先建立乙個全域性共享的佇列,佇列中只存在有限個元素,並將所有的資料逐條加入到佇列中,並呼叫佇列的join函式進行等待。之後便可以開啟若干執行緒,執行緒的任務就是不斷的從佇列中取資料進行處理就可以了。

#!/usr/bin/python

#coding=utf-8

import threading

import time

import queue

q = queue.queue(10)

threadlock = threading.lock()

class mythread(threading.thread):

def __init__(self,threadid,name):

threading.thread.__init__(self)

self.threadid = threadid

self.name = name

self.exitflag = 0

def run(self):

while not self.exitflag:

threadlock.acquire()

if not q.empty():

id = q.get()

print_time(self.name,id)

threadlock.release()

else:

threadlock.release()

def print_time(threadname,id):

pass

# print "%s:%s:%s"%(threadname,time.ctime(time.time()),id)

# 建立3個執行緒

threads =

for i in xrange(3):

name = "thread-%d"%i

t = mythread(i,name)

t.start()

for i in xrange(10000):

q_name = "queue:%d"%i

q.put(q_name)

# 等待佇列清空

while not q.empty():

pass

# 也可以join方法,與上同效

# q.join()

# 通知執行緒,處理完之後關閉

for t in threads:

t.exitflag = 1

# 等待所有執行緒結束之後才退出

for t in threads:

t.join()

print "exiting main thread"

這裡注意兩點,首先
while not q.empty():

pass

q.join()
兩者效果相同。

其次

threadlock.acquire()

if not q.empty():

這裡必須要在判斷q.empty()前加上執行緒鎖,因為可能會出現這樣的一種情況。

某一時刻,佇列中還有乙個元素,該元素正在被執行緒a取出,而與此同時執行緒b正在判斷佇列q是否為空,而此時執行緒b中佇列q不為空進入後面的操作,但是待b去取元素時,最後乙個元素已經被a取出,造成執行緒等待,顯示出被掛起的狀態。

我們也可以通過加入q.get(timeout=10)超時操作來彌補這一問題。

0x03 後記

由於python中的gil全域性鎖的原因,多執行緒效果並不怎麼好,併發處理網路或讀寫檔案效果還不錯,所以gg。

python中的佇列與執行緒

描述 1 理論上多執行緒執行任務是不能獲取返回結果的,因此需要乙個容器來儲存產生的資料 2 容器該如何選擇?list 棧,佇列 tuple 元組是不可變的,不可使用 set 集合缺省會去重,所以不選擇 dict 選擇佇列型別儲存 fifo first input first output impor...

python佇列執行緒池 Python多執行緒與佇列

多執行緒爬蟲對比單執行緒爬蟲有很大的優勢,雖然python中的多執行緒並不是真正意義上的多執行緒,執行緒不可以同時執行,而是順序序列執行的,只是在乙個執行緒在等待時,cpu切換到另外乙個執行緒接著幹活,這樣看起來就感覺像是並行。雖然如此,多執行緒的效率仍然比單執行緒快上很多倍,是爬蟲中不可缺少的技能...

Python多執行緒與多執行緒中join 的用法

文章 python多執行緒與多程序中join 方法的效果是相同的。下面僅以多執行緒為例 首先需要明確幾個概念 知識點一 當乙個程序啟動之後,會預設產生乙個主線程,因為執行緒是程式執行流的最小單元,當設定多執行緒時,主線程會建立多個子執行緒,在python中,預設情況下 其實就是setdaemon f...