并发编程之多线程
1.什么是線程?
線程指的是程序的執行線路,相當于一條流水線,包含了程序的具體執行步驟,一條流水線必須屬于一個車間,一個車間的工作過程就是一個進程,車間負責把資源整合到一起,是一個資源單位,而車間內至少有一條流水線,也就是說一個進程至少有一個線程。
進程是一個資源單位,線程是CPU的最小執行單位。
線程和進程的關系:進程包含了運行程序需要的所有資源,每一個進程一旦被創建,就默認開啟了一條線程,稱之為主線程。一個進程可以包含多個線程,而線程依賴進程。
2.什么是多線程?
多線程指的是在一個進程中存在多個線程,多個線程共享該進程的地址空間,相當于一個車間內有多條流水線,都公用一個車間的資源。
注:多進程之間內存地址是相互隔離的,多線程之間的資源是共享的。
3.為什么使用多線程?
因為多進程對操作系統的資源耗費非常高,每開一個進程都要申請內存空間,而開線程,就相當于在一個車間內造一條流水線,無需申請空間,對操作系統的資源耗費比較小。多線程可以使CPU在一個進程內進行切換,從而提到CPU的占用率,從而提高程序的效率。
應用場景:當遇到I/O操作時,就可以使用多線程。
進程和線程的區別:
1.進程對于操作系統的資源耗費非常高,而線程相反(比進程低10-100倍)。
2.在同一個進程中,多個線程之間資源共享的;多個進程之間,內存是相互隔離的,即資源不共享。
4.開啟線程的兩種方式
1.實例化Thread類的對象
from threading import Threaddef task():print('子線程。。。')t = Thread(target=task) t.start() print('主')# 子線程。。。 # 由于開啟線程的速度非常快,所以有可能的情況就是子線程一經開啟,就立馬執行其中代碼 # 主2.繼承Thread類,覆蓋run方法
class MyThread(Thread):def run(self):print("子線程 running....") MyThread().start() print("over2")5.多進程和多線程對比
1.開啟速度
from threading import Thread import time def task():pass start = time.time() l = [] for i in range(100):t = Thread(target=task)l.append(t)t.start() print(time.time()-start) for t in l:t.join() print('主')# 0.015770673751831055 # 主 開啟多個線程 from multiprocessing import Process import time def task():passl = [] if __name__ == '__main__':start = time.time()for i in range(100):p = Process(target=task)l.append(p)p.start()print(time.time()-start)for p in l:p.join()print('主')# 3.595005750656128 # 主 開啟多個進程2.PID
from multiprocessing import Process import time import osdef task1():print(os.getpid()) # 9528 def task2():print(os.getpid()) # 11704if __name__ == '__main__':p1 = Process(target=task1)p1.start()p2 = Process(target=task2)p2.start() 多進程的PID from threading import Thread import time import osdef task1():print(os.getpid()) # 7560 def task2():print(os.getpid()) # 7560if __name__ == '__main__':t1 = Thread(target=task1)t1.start()t2 = Thread(target=task2)t2.start() 多線程的PID3.數據共享
from threading import Threadx = 100 def task():global xx = 0 l = [] for i in range(100):t = Thread(target=task)t.start()l.append(t) for t in l:t.join() print(x) print('over')# 0 # over 多線程間數據共享 from multiprocessing import Processx = 100 def task():global xx = 0 l = [] if __name__ == '__main__':for i in range(100):t = Process(target=task)t.start()l.append(t)for t in l:t.join()print(x)print('over')# 100 # over 進程間數據數據不共享6.線程相關的其他方法
Thread實例對象的方法# isAlive(): 返回線程是否活動的。# getName(): 返回線程名。# setName(): 設置線程名。 threading模塊提供的一些方法:# threading.currentThread(): 返回當前的線程變量。# threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啟動后、結束前,不包括啟動前和終止后的線程。# threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。 from threading import Thread import threading from multiprocessing import Process import osdef work():import timetime.sleep(3)print(threading.current_thread().getName())if __name__ == '__main__':#在主進程下開啟線程t=Thread(target=work)t.start()print(threading.current_thread().getName())print(threading.current_thread()) #主線程print(threading.enumerate()) #連同主線程在內有兩個運行的線程print(threading.active_count())print('主線程/主進程')'''打印結果:MainThread<_MainThread(MainThread, started 140735268892672)>[<_MainThread(MainThread, started 140735268892672)>, <Thread(Thread-1, started 123145307557888)>]主線程/主進程Thread-1''' View Code7.守護線程
守護線程會在所有非守護線程結束后結束。主線程在其他非守護線程運行完畢后才算運行完畢(守護線程在此時進行回收),因為主線程的結束意味著進程的結束,進程整體的資源都將被回收,而進程必須保證非守護線程都運行完畢后才能結束。
from threading import Thread import timedef task():print('子線程 run....')time.sleep(0.1)print('子線程 over...')t = Thread(target=task) t.daemon = True # 必須在start前 t.start() print('主線程 over...')# 子線程 run.... # 主線程 over... from threading import Thread import time def task1():print('子線程1 run....')time.sleep(0.1)print('子線程1 over...') def task2():print('子線程2 run....')# time.sleep(1)print('子線程2 over...')t1 = Thread(target=task1) t2 = Thread(target=task2) t1.daemon = True # 必須在start前 t1.start() t2.start() print('主線程 over...')# 子線程1 run.... # 子線程2 run.... # 子線程2 over... # 主線程 over... 例28.線程互斥鎖
當多個線程需要同時修改同一份數據時,可能會造成數據錯亂,所以這時必須加鎖。
from threading import Thread,Lock import time lock = Lock() x = 100 def task():lock.acquire()global xt = x - 1time.sleep(0.01)x = tlock.release()l = [] for i in range(100):t = Thread(target=task)t.start()l.append(t) for t in l:t.join() print(x) print('over')# 0 # over 線程互斥鎖信號量:也是一種鎖,其特點是可以設置一個數據可以被幾個線程(進程)共享,即可以讓這個數據在同一時間能被多個線程使用。它的應用場景是可以限制一個數據被同時訪問的次數,保證程序正常運行。
from threading import Thread,Semaphore,current_thread import time sem = Semaphore(4) # 其中的參數可以設置有幾個線程可以同時共享數據 def task():sem.acquire()print('%s run...' % current_thread())time.sleep(2)sem.release()for i in range(10):t = Thread(target=task)t.start()線程互斥鎖與信號量圖解
http://url.cn/5DMsS9r轉載于:https://www.cnblogs.com/wangke0917/p/10209175.html
總結
- 上一篇: C# 模拟 鼠标 键盘操作
- 下一篇: 简单的 php 防注入、防跨站 函数