线程死锁与共享变量的使用(转载)
生活随笔
收集整理的這篇文章主要介紹了
线程死锁与共享变量的使用(转载)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?
通過輪詢的方式解決線程間共享全局變量的問題
from threading import Threadg_num = 0 g_flag = 1 # 增加一個標識全局變量def test1():global g_numglobal g_flagif g_flag == 1:for i in range(1000000):g_num += 1g_flag = 0print('---test1 g_num is %d---' % g_num)def test2():global g_num# 輪詢while True:if g_flag != 1: # 一旦test1()執行完,即g_flag = 0時,test2()開始執行累加g_num操作for i in range(1000000):g_num += 1breakprint('---test2 g_num is %d---' % g_num)t1 = Thread(target=test1) t1.start()t2 = Thread(target=test2) t2.start()print('-----g_num: %d-----' % g_num)?
線程間使用非全局變量
from threading import Thread import threading import timedef test1():name = threading.current_thread().name # 獲取當前線程名字print('----thread name is %s----' % name)g_num = 100if name == 'Thread-1':g_num += 1else:time.sleep(2)print('---thread is %s | g_num is %d---' % (name, g_num))t1 = Thread(target=test1) t1.start()t2 = Thread(target=test1) t2.start()通過互斥鎖解決線程間共享全局變量的問題
from threading import Thread, Lock # 導入互斥鎖g_num = 0def test1():global g_numfor i in range(1000000):mutex.acquire() # 上鎖,此時其他的鎖會等待 上鎖應該遵循最小原則g_num += 1mutex.release() # 開鎖,此時其他的鎖會搶著開鎖print('---test1 g_num is %d---' % g_num)def test2():global g_numfor i in range(1000000):mutex.acquire()g_num += 1mutex.release()print('---test2 g_num is %d---' % g_num)# 創建一把互斥鎖,默認不上鎖 mutex = Lock()t1 = Thread(target=test1) t1.start()t2 = Thread(target=test2) t2.start()print('-----g_num: %d-----' % g_num)?
通過互斥鎖解決線程間共享全局變量的問題-修改后的代碼
from threading import Thread, Lock # 導入互斥鎖g_num = 0def test1():global g_nummutex.acquire() # 上鎖,此時其他的鎖會等待 上鎖應該遵循最小原則for i in range(1000000):g_num += 1mutex.release() # 開鎖,此時其他的鎖會搶著開鎖print('---test1 g_num is %d---' % g_num)def test2():global g_nummutex.acquire()for i in range(1000000):g_num += 1mutex.release()print('---test2 g_num is %d---' % g_num)# 創建一把互斥鎖,默認不上鎖 mutex = Lock()t1 = Thread(target=test1) t1.start()t2 = Thread(target=test2) t2.start()print('-----g_num: %d-----' % g_num)# 值得注意的是,互斥鎖上的范圍太大就失去了線程的意義,別的線程都把時間浪費在了等待上.輪詢同理.線程死鎖
import threading import timeclass MyThread1(threading.Thread):def run(self):if mutexA.acquire():print(self.name + '---do1---up---')time.sleep(1)if mutexB.acquire():print(self.name + '---do1---down---')mutexB.release()mutexA.release()class MyThread2(threading.Thread):def run(self):if mutexB.acquire():print(self.name + '---do2---up---')time.sleep(1)if mutexA.acquire():print(self.name + '---do2---down---')mutexA.release()mutexB.release()if __name__ == '__main__':mutexA = threading.Lock()mutexB = threading.Lock()t1 = MyThread1()t2 = MyThread2()t1.start()t2.start()分析代碼,t1的代碼在等待mutexB解鎖的時候t2在等待mutexA解鎖.
而t1必須先執行完mutexB鎖中的代碼執行完才能釋放mutexA,
t2必須先執行完mutexA鎖中的代碼執行完才能釋放mutexB,
這就導致兩個線程一直等待下去形成死鎖,會浪費CPU資源.
解決死鎖辦法:
設置超時時間 mutexA.acquire(2)
當然也可以從算法上避免死鎖
?
使用ThreadLocal
import threading# 創建全局ThreadLocal對象 local_school = threading.local()def process_student():# 獲取當前線程相關聯的studentstd = local_school.studentprint('Hello, %s in %s' % (std, threading.current_thread().name))def process_thread(name):# 綁定ThreadLocal的studentlocal_school.student = nameprocess_student()t1 = threading.Thread(target=process_thread, args=('kain',), name='Thread-A') t2 = threading.Thread(target=process_thread, args=('huck',), name='Thread-B')t1.start() t2.start() t1.join() t2.join()ThreadLocal是一個線程內部的數據存儲類,通過它可以在指定的線程中存儲數據,數據存儲以后,只有在指定的線程中可以獲取到存儲的數據,對于其他線程來說則無法取到數據。
?
生產者和消費者問題
import threading import time# Python2 # from Queue import Queue# Python3 from queue import Queueclass Producer(threading.Thread):def run(self):global queuecount = 0while True:if queue.qsize() < 1000:for i in range(100):count += 1msg = '生成產品' + str(count)queue.put(msg)print(msg)time.sleep(0.5)class Consumer(threading.Thread):def run(self):global queuewhile 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()for i in range(500):queue.put('初始產品'+str(i)) # 向隊列中塞內容for i in range(2):p = Producer()p.start()for i in range(5):c = Consumer()c.start()?
總結
以上是生活随笔為你收集整理的线程死锁与共享变量的使用(转载)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Yy评级(2021yy全业务排名表)
- 下一篇: 火龙果馒头蒸出来为什么不是红色的