Python多線程(二): 線程同步 & 生產者消費者模式 & ThreadLocal線程局部變量

線程同步 

     同步就是協同步調,按預定的先後次序進行運行。例如:開會。“同”字指協同、協助、互相配合。

     如進程、線程同步,可以理解爲進程或線程 A 和 B 一塊配合, A 執行到一定程度時要依靠 B 的某個結果,於是停下來,示意 B 運行, B 運行後將結果給 A, A 繼續運行

 

線程同步應用
 

import time
from threading import Thread,Lock
import threading

lock1=Lock()
lock2=Lock()
lock3=Lock()
lock2.acquire()
lock3.acquire()

class Task1(Thread):
	def run(self):
		while True:
			if lock1.acquire():
				print('...task1...')
				time.sleep(1)
				lock2.release()

class Task2(Thread):
	def run(self):
		while True:
			if lock2.acquire():
				print('...task2...')
				time.sleep(1)
				lock3.release()

class Task3(Thread):
	def run(self):
		while True:
			if lock3.acquire():
				print('...task3...')
				time.sleep(1)
				lock1.release()

if __name__ == '__main__':
	t1=Task1()
	t2=Task2()
	t3=Task3()
	t1.start()
	t2.start()
	t3.start()

 

生產者-消費者模式

        生產者就是生產數據的線程,消費者就是消費數據的線程。在多線程開發當中,如果生產者處理速度很快,而消費者處理速度很慢,那麼生產者就必須等待消費者處理完,才能繼續生產數據。同樣的道理,如果消費者的處理能力大於生產者,那麼消費者就必須等待生產者。爲了解決這個問題於是引入生產者和消費者模式

       生產者消費者模式通過一個容器來解決生產者和消費者的強耦合問題生產者和消費者之間不直接通信。 生產者生產商品, 然後將其放到類似隊列的數據結構中, 消費者不找生產者要數據,而是直接從隊列中取。 這裏使用 queue 模塊來提供線程間通信的機制,也就是說,生產者和消費者共享一個隊列。生產者生產商品後,會將商品添加到隊列中。消費者消費商品,會從隊列中取出商品
 

import time
import threading
from queue import Queue

class Producer(threading.Thread):
	def run(self):
		global queue
		count=0
		while True:
			if queue.qsize()<1000:
				for i in range(100):
					count += 1
					msg = '生成產品' + str(count)
					queue.put(msg)
					print(msg)
			time.sleep(0.5)

class Consumer(threading.Thread):
	def run(self):
		global queue
		while True:
			if queue.qsize()>100:
				for i in range(3):
					msg=self.name+'消費了'+queue.get()
					print(msg)
			time.sleep(1)

if __name__ == '__main__':
	queue = Queue()
	p=Producer()
	p.start()
	time.sleep(1)
	c=Consumer()
	c.start()

 

ThreadLocal線程局部變量

       我們知道多線程環境下,每一個線程均可以使用所屬進程的全局變量。如果一個線程對全局變量進行了修改,將會影響到其他所有的線程對全局變量的計算操作,從而出現數據混亂,即爲髒數據。爲了避免多個線程同時對變量進行修改,引入了線程同步機制,通過互斥鎖來控制對全局變量的訪問。所以有時候線程使用局部變量比全局變量好,因爲局部變量只有線程自身可以訪問,同一個進程下的其他線程不可訪問


       從上面的實例可以看到每個函數一層一層調用都需要傳遞 std 參數,非常麻煩,如果使用全局變量也不行,因爲每個線程處理不同的 Student 對象,不能共享。 因此 Python 還提供了ThreadLocal 變量,它本身是一個全局變量,但是每個線程卻可以利用它來保存屬於自己的私有數據,這些私有數據對其他線程也是不可見的
 

import threading

# 創建全局 ThreadLocal 對象:
local = threading.local()

def process_student():
	# 獲取當前線程關聯的 name:
	student_name = local.name
	print('線程名: %s 學生姓名:%s' % (threading.current_thread().name,student_name))

def process_thread(name):
	# 綁定 ThreadLocal 的 name:
	local.name = name
	process_student()

t1 = threading.Thread(target=process_thread, args=('張三',), name='Thread-A')
t2 = threading.Thread(target=process_thread, args=('李四',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章