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

溫馨提示×

溫馨提示×

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

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

python多線程之間如何同步

發布時間:2021-08-26 11:11:24 來源:億速云 閱讀:175 作者:小新 欄目:開發技術

這篇文章主要介紹了python多線程之間如何同步,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

引言:

線程之間經常需要協同工作,通過某種技術,讓一個線程訪問某些數據時,其它線程不能訪問這些數據,直到該線程完成對數據的操作。這些技術包括臨界區(Critical Section),互斥量(Mutex),信號量(Semaphore),事件Event等。

Event

 threading庫中的event對象通過使用內部一個flag標記,通過flag的True或者False的變化來進行操作。

     名稱                                     含義
set( )標記設置為True
clear( )標記設置為False
is_set( )標記是否為True
wait(timeout=None)設置等待標記為True的時長,None為無限等待。等到返回True,等不到返回False
from threading import Thread,Event
import time

def creditor(event:Event):
 print("什么時候還我錢")
 event.wait()
 print("我已經等了很長時間了")


def debtor(event:Event,count=10):
 print("可以寬裕幾天嗎?")
 money=[]
 while True:
 print("先還你100")
 time.sleep(0.5)
 money.append(1)
 if len(money)>count:
  event.set()
  break
 print("我已經還完你的錢了")

event=Event()
c=Thread(target=creditor,args=(event,))
d=Thread(target=debtor,args=(event,))
c.start()
d.start()

運行結果如下所示:

python多線程之間如何同步

可以看到creditor函數中因為event.wait( )線程進入等待狀態,此時debtor線程進入運行,當滿足條件時event.set( )將標記設置為True,creditor線程開始運行。誰wait就是等到flag變為True,或等到超時變為False。不限制等待的個數。

wait的使用

from threading import Event,Thread


def Wait(event:Event,interval):
 while not event.wait(interval):
 print("waiting for you")

e=Event()
Thread(target=Wait,args=(e,3)).start()
e.wait(10)
e.set()
print("main exit")

python多線程之間如何同步

主線程一開始就wait 10s,Waiting線程等待3s返回False,進入循環打印"waiting for you",重復3次,然后主線程set了,這時候Waiting線程變為True,不再進入循環。

Lock

凡是存在資源爭用的地方都可以使用鎖,從而保證只有一個使用者可以完全使用這個資源

現在要生產10個杯子,由10個工人開始生產

import threading
import time 

cups=[]

def worker(count=10):
 print("我是{},我開始生產了".format(threading.current_thread().name))
 flag=False
 while True:
 if len(cups)>count:
  flag=True
 time.sleep(0.05)
 if not flag:
  cups.append(1)
 if flag:
  break 
 print("finished.cups={}".format(len(cups)))
 
for _ in range(10):
 threading.Thread(target=worker,args=(1000,)).start()

運行結果如下圖所示:

python多線程之間如何同步

我們明明只需要到1000就會break,但是結果卻到了1010個,這就是因為有10個線程,其中每個線程都在增加,但是增加后的數目,其他線程并不會知道(每個線程通過len函數拿到數量,但是剛拿到數字,其他線程就立即更新了)

這個時候我們就需要鎖lock來實現了,一旦線程獲得鎖,其他試圖獲取鎖的線程將被阻塞

      名稱                               含義
acquire(blocking=True,timeout=-1)默認阻塞,阻塞可以設置超時時間。非阻塞時,timeout禁止設置。成功獲取鎖,返回True,否則返回False
release( )釋放鎖。可以從任何線程釋放。已上鎖的鎖,會拋出RuntimeError異常

加鎖的實現:

import threading 
import time 

cups=[]
lock=threading.Lock()

def worker(count=10):
 print("我是{},我開始生產了".format(threading.current_thread().name))
 flag=False
 while True:
 lock.acquire()
 if len(cups)>=count:
  flag=True
 time.sleep(0.005)
 if not flag:
  cups.append(1)
 lock.release()
 if flag:
  break
 print("finished,cups={}".format(len(cups)))
 
for _ in range(10):
 threading.Thread(target=worker,args=(1000,)).start()

運行結果如圖所示:

python多線程之間如何同步

一般來說加鎖后還需要一些代碼實現,在釋放鎖之前還有可能拋出異常,一旦出現異常,鎖無法釋放,但是當前這個線程會因為這個異常而終止,這樣會產生死鎖,因此使用時要使用如下的方法:

1,使用try...finally語句保證鎖的釋放

2,with安全上下文管理(鎖對象支持上下文管理)

計數器類,用來加,減。

import threading
import time


class Counter:
 def __init__(self):
 self._val = 0
 self.__lock = threading.Lock()

 @property
 def value(self):
 return self._val

 def inc(self):
 try:
  self.__lock.acquire()
  self._val += 1
 finally:
  self.__lock.release()

 def dec(self):
 with self.__lock:
  self._val -= 1


def run(c: Counter, count=100):
 for _ in range(count):
 for i in range(-50, 50):
  if i < 0:
  c.dec()
  else:
  c.inc()


c = Counter()
c1 = 10
c2 = 1000


for i in range(c1):
 threading.Thread(target=run, args=(c, c2)).start()


while True:
 if threading.active_count() == 1:
 print(c.value)
 break

啟動了10個線程,1000次從-50到50進行加減,最后得到0,如果沒有加鎖處理的話,得到的結果未必是自己想要的。

鎖的使用場景:

鎖適用于訪問和修改同一個資源的時候,引起資源爭用的情況下。使用鎖的注意事項:

  1. 1,少用鎖,除非有必要。多線程訪問加鎖的資源時,由于鎖的存在,實際就變成了串行。

  2. 2,加鎖時間越短越好,不需要就立即釋放鎖。

  3. 3,一定要避免死鎖,使用with或者try...finally。

非阻塞鎖使用

import threading
import time


def worker(tasks):
 for task in tasks:
 time.sleep(0.001)
 if task.lock.acquire(False):
  print("{} {} begin to start".format(threading.current_thread(),task.name))
 else:
  print("{} {} is working".format(threading.current_thread(),task.name))


class Task:
 def __init__(self,name):
 self.name=name
 self.lock=threading.Lock()

tasks=[Task('task-{}'.format(x)) for x in range(10)]

for i in range(5):
 threading.Thread(target=worker,name="worker-{}".format(i),args=(tasks,)).start()

運行結果如下圖所示:

python多線程之間如何同步

總共開啟了5個線程,每個線程處理10個任務,因為在if語句里面,task.lock.acquire(False),所以每個線程只有拿到鎖是True,其他的線程不會阻塞會返回False。打印"is working"。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“python多線程之間如何同步”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

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

AI

马龙县| 宜君县| 上饶市| 明溪县| 太原市| 南丰县| 临澧县| 湖口县| 崇信县| 娄烦县| 恩平市| 长子县| 清水县| 巴塘县| 双辽市| 盈江县| 藁城市| 南乐县| 秦安县| 长治市| 都安| 六安市| 湾仔区| 西丰县| 延川县| 马公市| 花莲县| 乐都县| 留坝县| 瑞丽市| 重庆市| 石阡县| 罗平县| 永泰县| 垣曲县| 昌都县| 万安县| 洞口县| 高碑店市| 若尔盖县| 肇州县|