線程的理解應該結合進程來對比理解更直接 如果我們操作系統當做一個工廠的話,那麼創建一個進程就相當於在這個工廠裡面新增了一個車間,車間裡面存放了很多資源,而車間要運行起來很顯然的標誌就是流水線,而這些流水線就是線程,可以說線程是執行代碼的最小單位。 而線程和進程兩者在使用層面上有很大的相似性,所以開啟 ...
線程的理解應該結合進程來對比理解更直接
如果我們操作系統當做一個工廠的話,那麼創建一個進程就相當於在這個工廠裡面新增了一個車間,車間裡面存放了很多資源,而車間要運行起來很顯然的標誌就是流水線,而這些流水線就是線程,可以說線程是執行代碼的最小單位。
而線程和進程兩者在使用層面上有很大的相似性,所以開啟或者說創建線程的2種方式跟創建進程很相似,區別在於導入的模塊和類不一樣而已。
一、開啟線程方法:
第一種:
from threading import Thread import time def task(name): time.sleep(2) print('%s has no jj' %name) if __name__ == '__main__': t=Thread(target=task,args=('JJ',)) t.start() print('主')
第二種:
from threading import Thread import time class MyThread(Thread): def __init__(self, name): super().__init__() self.name = name def run(self): print("%s is running" % self.name) time.sleep(1) print("%s is done" % self.name) t1 = MyThread('Mr hello') t1.start() t1.join() print('zhuzhuzhu')
二、線程之間的數據共用
前面我們學到進程的時候知道進程與進程之間記憶體空間是相互隔離的,互相無法直接訪問到,那麼線程之間的共用呢
下麵通過一段代碼來看看數據直接是否共用:
from threading import Thread x= 99 def task(): global x x = 66 t1 = Thread(target=task) # 創建子線程對象 t1.start() # 向操作系統發送子線程執行請求 t1.join() # 子線程完畢後才往下走,此時子進程已經執行了x = 66,如果最終列印 # 的是99,則代表子進程無法修改主進程中的x,如果是66則子進程與主進程公共一記憶體空間,可以修改 print(x) # 結果為66,證明公用一個記憶體空間
可以看到,線程之間的數據時具有共用性的,所以就會存在一個隱患,當多個線程同時併發操作同一數據時候或者執行同一代碼的時候在某種場景下會導致混亂。
這就是我們後面學到的GIL(global interpreter lock)全局解釋器鎖的必要性的原因。在這裡先提一下。
三、線程的互斥鎖:
線程的互斥鎖,同理進程的互斥鎖,作用也是為了保證數據的安全,何種情況:多線程同時訪問操作同一數據時候
先產生鎖,再在操作數據的那段代碼前後加鎖,操作完畢釋放鎖。實現方法:
from threading import Thread, Lock import time import random import json mutex = Lock() # 創建鎖 class MyThread(Thread): def __init__(self, name): super().__init__() self.name = name def run(self): time.sleep(0.5) #保證多線程同一時間搶鎖,睡個0.5秒,等待大部分線程都能運行到此處,開始搶鎖 mutex.acquire() # 加鎖 with open('info', 'r', encoding='utf-8') as f1: # 簡單模擬搶票過程 dic = json.load(f1) num = dic.get('remain') # time.sleep(random.randint(1, 5)) print('剩餘票數:%s' % num) if not num: print('票已售完,%s購票失敗' % self.name) else: dic['remain'] -= 1 # time.sleep(random.randint(1, 5)) with open('info', 'w', encoding='utf-8') as f2: json.dump(dic, f2) print('用戶%s購票成功!' % self.name) mutex.release() # 釋放鎖,這裡註意釋放位置 user2 = MyThread('egon') user3 = MyThread('jason') user1 = MyThread('alex') user2.start() user3.start() user1.start() user1.join() user2.join() user3.join() print('歡迎歡迎')