91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

詳解python多線程、鎖、event事件機制的簡單使用

發布時間:2020-09-25 02:04:12 來源:腳本之家 閱讀:237 作者:君惜 欄目:開發技術

線程和進程

1、線程共享創建它的進程的地址空間,進程有自己的地址空間

2、線程可以訪問進程所有的數據,線程可以相互訪問

3、線程之間的數據是獨立的

4、子進程復制線程的數據

5、子進程啟動后是獨立的 ,父進程只能殺掉子進程,而不能進行數據交換

6、修改線程中的數據,都是會影響其他的線程,而對于進程的更改,不會影響子進程

threading.Thread

Thread 是threading模塊中最重要的類之一,可以使用它來創建線程。有兩種方式來創建線程:一種是通過繼承Thread類,重寫它的run方法;另一種是創建一個threading.Thread對象,在它的初始化函數(__init__)中將可調用對象作為參數傳入。
先來看看通過繼承threading.Thread類來創建線程的例子:

import threading
import time

class MyThread(threading.Thread):
 def __init__(self, arg):
  # super(MyThread, self).__init__() # 新式類繼承原有方法寫法
  threading.Thread.__init__(self)
  self.arg = arg

 def run(self):
  time.sleep(2)
  print(self.arg)

for i in range(10):
 thread = MyThread(i)
 print(thread.name)
 thread.start()

另外一種創建線程的方法:

import threading
import time

def process(arg):
 time.sleep(2)
 print(arg)

for i in range(10):
 t = threading.Thread(target=process, args=(i,))
 print(t.name)
 t.start()

Thread類還定義了以下常用方法與屬性:

Thread.getName() 獲取線程名稱

Thread.setName() 設置線程名稱

Thread.name 線程名稱

Thread.ident 獲取線程的標識符。線程標識符是一個非零整數,只有在調用了start()方法之后該屬性才有效,否則它只返回None

判斷線程是否是激活的(alive)。從調用start()方法啟動線程,到run()方法執行完畢或遇到未處理異常而中斷 這段時間內,線程是激活的

Thread.is_alive()
Thread.isAlive()

Thread.join([timeout]) 調用Thread.join將會使主調線程堵塞,直到被調用線程運行結束或超時。參數timeout是一個數值類型,表示超時時間,如果未提供該參數,那么主調線程將一直堵塞到被調線程結束

Python GIL(Global Interpreter Lock)

GIL并不是Python的特性,它是在實現Python解析器(CPython)時所引入的一個概念。就好比C++是一套語言(語法)標準,但是可以用不同的編譯器來編譯成可執行代碼。有名的編譯器例如GCC,INTEL C++,Visual C++等。Python也一樣,同樣一段代碼可以通過CPython,PyPy,Psyco等不同的Python執行環境來執行。像其中的JPython就沒有GIL。然而因為CPython是大部分環境下默認的Python執行環境。所以在很多人的概念里CPython就是Python,也就想當然的把GIL歸結為Python語言的缺陷。所以這里要先明確一點:GIL并不是Python的特性,Python完全可以不依賴于GIL。

線程鎖的使用:

# 鎖:GIL 全局解釋器 它是為了保證線程在運行過程中不被搶占
number = 0
lock = threading.RLock() # 創建鎖


def run(num):
 lock.acquire() # 加鎖
 global number
 number += 1
 print(number)
 time.sleep(2)
 lock.release() # 釋放鎖

for i in range(10):
 t = threading.Thread(target=run, args=(i, ))
 t.start()

Join & Daemon

主線程A中,創建了子線程B,并且在主線程A中調用了B.setDaemon(),這個的意思是,把主線程A設置為守護線程,這時候,要是主線程A執行結束了,就不管子線程B是否完成,一并和主線程A退出.這就是setDaemon方法的含義,這基本和join是相反的。此外,還有個要特別注意的:必須在start() 方法調用之前設置,如果不設置為守護線程,程序會被無限掛起。

class MyThread1(threading.Thread):
 def __init__(self):
  threading.Thread.__init__(self)

 def run(self):
  print("thread start")
  time.sleep(3)
  print('thread end')

print('main start')
thread1 = MyThread1()
# thread1.setDaemon(True)  # 設置子線程是否跟隨主線程一起結束
thread1.start()
time.sleep(1)
print('satrt join')
# thread1.join() # 使主線程阻塞,直至子線程運行完畢再繼續主線程
print('end join')
def run(n):
 print('[%s]------running----\n' % n)
 time.sleep(2)
 print('--done--')


def main():
 for i in range(5):
  t = threading.Thread(target=run, args=[i,])
  t.start()
  # t.join()
  print('starting thread', t.getName())


m = threading.Thread(target=main,args=[])
# m.setDaemon(True) # 將主線程設置為Daemon線程,它退出時,其它子線程會同時退出,不管是否執行完任務
m.start()
# m.join() # 使主線程阻塞,直至子線程運行完畢再繼續主線程
print("---main thread done----")

線程鎖(互斥鎖Mutex)

一個進程下可以啟動多個線程,多個線程共享父進程的內存空間,也就意味著每個線程可以訪問同一份數據,此時,如果2個線程同時要修改同一份數據,會出現什么狀況?

num = 100 # 設定一個共享變量
def subNum():
 global num # 在每個線程中都獲取這個全局變量
 print('--get num:', num)
 time.sleep(2)
 num -= 1 # 對此公共變量進行-1操作
thread_list = []
for i in range(100):
 t = threading.Thread(target=subNum)
 t.start()
 thread_list.append(t)
for t in thread_list: # 等待所有線程執行完畢
 t.join()
print('final num:', num)
# 加鎖版本
def subNum():
 global num # 在每個線程中都獲取這個全局變量
 print('--get num:', num)
 time.sleep(1)
 lock.acquire() # 修改數據前加鎖
 num -= 1 # 對此公共變量進行-1操作
 lock.release() # 修改后釋放

num = 100 # 設定一個共享變量
thread_list = []
lock = threading.Lock() # 生成全局鎖
for i in range(100):
 t = threading.Thread(target=subNum)
 t.start()
 thread_list.append(t)
for t in thread_list: # 等待所有線程執行完畢
 t.join()
print('final num:', num)

Rlock與Lock的區別:

RLock允許在同一線程中被多次acquire。而Lock卻不允許這種情況。否則會出現死循環,程序不知道解哪一把鎖。注意:如果使用RLock,那么acquire和release必須成對出現,即調用了n次acquire,必須調用n次的release才能真正釋放所占用的鎖

Events

Python提供了Event對象用于線程間通信,它是由線程設置的信號標志,如果信號標志位真,則其他線程等待直到信號接觸。
Event對象實現了簡單的線程通信機制,它提供了設置信號,清除信號,等待等用于實現線程間的通信。

event = threading.Event() 創建一個event

1 設置信號
event.set()

使用Event的set()方法可以設置Event對象內部的信號標志為真。Event對象提供了isSet()方法來判斷其內部信號標志的狀態。
當使用event對象的set()方法后,isSet()方法返回真

2 清除信號
event.clear()

使用Event對象的clear()方法可以清除Event對象內部的信號標志,即將其設為假,當使用Event的clear方法后,isSet()方法返回假

3 等待
event.wait()

Event對象wait的方法只有在內部信號為真的時候才會很快的執行并完成返回。當Event對象的內部信號標志位假時,
則wait方法一直等待到其為真時才返回。也就是說必須set新號標志位真

def do(event):
 print('start')
 event.wait()
 print('execute')

event_obj = threading.Event()
for i in range(10):
 t = threading.Thread(target=do, args=(event_obj,))
 t.start()

event_obj.clear()
inp = input('輸入內容:')
if inp == 'true':
 event_obj.set()

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

淮阳县| 辉南县| 眉山市| 莱西市| 宕昌县| 旌德县| 林口县| 启东市| 滕州市| 天长市| 韶山市| 含山县| 永安市| 家居| 共和县| 边坝县| 马尔康县| 绩溪县| 平凉市| 上栗县| 叶城县| 临朐县| 民权县| 镇坪县| 健康| 凤城市| 阳江市| 游戏| 德安县| 泉州市| 诸暨市| 九江市| 淳安县| 张家川| 武清区| 丽水市| 阜城县| 改则县| 通江县| 中牟县| 喀喇沁旗|