黄色电影一区二区,韩国少妇自慰A片免费看,精品人妻少妇一级毛片免费蜜桃AV按摩师 ,超碰 香蕉

Python 線程通信

python 線程通信

在現(xiàn)實生活中,如果一個團(tuán)隊正在開展一項共同任務(wù),那么他們之間應(yīng)該進(jìn)行溝通以正確完成任務(wù)。同樣的類比也適用于線程。在編程中,為了減少處理器的理想時間,我們創(chuàng)建多個線程并為每個線程分配不同的子任務(wù)。因此,必須有一個通信設(shè)施,他們應(yīng)該相互交互,以同步的方式完成工作。

考慮以下與線程互通有關(guān)的要點 -

  • 沒有性能提升 - 如果我們無法在線程和進(jìn)程之間實現(xiàn)正確的通信,那么并發(fā)性和并行性帶來的性能提升是沒有用的。

  • 正確完成任務(wù) - 如果線程之間沒有適當(dāng)?shù)南嗷ネㄐ艡C(jī)制,則無法正確完成分配的任務(wù)。

  • 比進(jìn)程 間通信更有效 - 線程 間通信比進(jìn)程 間通信更高效,更易于使用,因為進(jìn)程內(nèi)的所有線程共享相同的地址空間,并且不需要使用共享內(nèi)存。

 

用于線程安全通信的python數(shù)據(jù)結(jié)構(gòu)

多線程代碼會出現(xiàn)將信息從一個線程傳遞到另一個線程的問題。標(biāo)準(zhǔn)通信原語無法解決此問題。因此,我們需要實現(xiàn)自己的復(fù)合對象,以便在線程之間共享對象,以使通信成為線程安全的。以下是一些數(shù)據(jù)結(jié)構(gòu),它們在對其進(jìn)行一些更改后提供了線程安全的通信

為了以線程安全的方式使用set數(shù)據(jù)結(jié)構(gòu),我們需要擴(kuò)展set類來實現(xiàn)我們自己的鎖定機(jī)制。

這是一個擴(kuò)展類的python示例 -

class extend_class(set):
   def __init__(self, *args, **kwargs):
      self._lock = lock()
      super(extend_class, self).__init__(*args, **kwargs)

   def add(self, elem):
      self._lock.acquire()
      try:
      super(extend_class, self).add(elem)
      finally:
      self._lock.release()

   def delete(self, elem):
      self._lock.acquire()
      try:
      super(extend_class, self).delete(elem)
      finally:
      self._lock.release()

在上面的示例中,定義了一個名為 extend_class 的類對象,該對象繼承自python 集合類。在此類的構(gòu)造函數(shù)中創(chuàng)建一個鎖對象?,F(xiàn)在,有兩個函數(shù) - add() 和 delete() 。這些函數(shù)是定義的并且是線程安全的。它們都依賴于 超 類功能和一個關(guān)鍵異常。

裝飾

這是線程安全通信的另一個關(guān)鍵方法,就是使用裝飾器。

考慮一個python示例,演示如何使用裝飾器和mminus;

def lock_decorator(method):

   def new_deco_method(self, *args, **kwargs):
      with self._lock:
         return method(self, *args, **kwargs)
return new_deco_method

class decorator_class(set):
   def __init__(self, *args, **kwargs):
      self._lock = lock()
      super(decorator_class, self).__init__(*args, **kwargs)

   @lock_decorator
   def add(self, *args, **kwargs):
      return super(decorator_class, self).add(elem)
   @lock_decorator
   def delete(self, *args, **kwargs):
      return super(decorator_class, self).delete(elem)

在上面的示例中,定義了一個名為lock_decorator的裝飾器方法,該方法繼承自python方法類。然后在此類的構(gòu)造函數(shù)中創(chuàng)建一個鎖對象。現(xiàn)在,有兩個函數(shù) - add()和delete()。這些函數(shù)是定義的并且是線程安全的。它們都依賴于超類功能和一個關(guān)鍵異常。

清單

列表數(shù)據(jù)結(jié)構(gòu)是線程安全的,快速的以及用于臨時內(nèi)存存儲的簡單結(jié)構(gòu)。在cpython中,gil可以防止對它們的并發(fā)訪問。我們開始知道列表是線程安全的但是它們中的數(shù)據(jù)呢。實際上,列表的數(shù)據(jù)不受保護(hù)。例如,如果另一個線程試圖做同樣的事情,則 l.append(x) 不保證返回預(yù)期的結(jié)果。這是因為雖然 append() 是一個原子操作并且是線程安全的,但另一個線程試圖以并發(fā)方式修改列表的數(shù)據(jù),因此我們可以看到競爭條件對輸出的副作用。

要解決此類問題并安全地修改數(shù)據(jù),我們必須實現(xiàn)適當(dāng)?shù)逆i定機(jī)制,這進(jìn)一步確保多個線程不會潛在地遇到競爭條件。為了實現(xiàn)正確的鎖定機(jī)制,我們可以像前面的例子中那樣擴(kuò)展類。

列表上的其他一些原子操作如下

l.append(x)
l1.extend(l2)
x = l[i]
x = l.pop()
l1[i:j] = l2
l.sort()
x = y
x.field = y
d[x] = y
d1.update(d2)
d.keys()

在這里

  • l,l1,l2都是列表
  • d,d1,d2是字典
  • x,y是對象
  • i,j是整數(shù)

隊列

如果列表的數(shù)據(jù)不受保護(hù),我們可能不得不面對后果。我們可能會獲取或刪除錯誤的數(shù)據(jù)項,競爭條件。這就是為什么建議使用隊列數(shù)據(jù)結(jié)構(gòu)。一個真實的隊列示例可以是單車道單向道路,車輛首先進(jìn)入,首先退出??梢栽谑燮贝翱诤凸财囌究吹礁嗾鎸嵤澜绲睦?。

隊列是默認(rèn)的,線程安全的數(shù)據(jù)結(jié)構(gòu),我們不必?fù)?dān)心實現(xiàn)復(fù)雜的鎖定機(jī)制。python為我們提供了 模塊在我們的應(yīng)用程序中使用不同類型的隊列。

 

隊列類型

在本節(jié)中,我們將了解不同類型的隊列。python提供了三個隊列選項,可以從 < queue> 模塊中使用

  • 正常隊列(fifo,先進(jìn)先出)
  • lifo,后進(jìn)先出
  • 優(yōu)先

我們將在后續(xù)章節(jié)中了解不同的隊列。

 

正常隊列(fifo,先進(jìn)先出)

它是python提供的最常用的隊列實現(xiàn)。在這種排隊機(jī)制中,無論誰先到,都會先獲得服務(wù)。fifo也稱為普通隊列。

 

fifo隊列的python實現(xiàn)

在python中,fifo隊列可以用單線程和多線程實現(xiàn)。

單線程fifo隊列

為了使用單線程實現(xiàn)fifo隊列, queue 類將實現(xiàn)一個基本的先進(jìn)先出容器。元素將使用 put() 添加到序列的一個“結(jié)尾” ,并使用 get() 從另一端刪除。

以下是用于實現(xiàn)單線程fifo隊列的python程序

import queue

q = queue.queue()

for i in range(8):
   q.put("item-" + str(i))

while not q.empty():
   print (q.get(), end = " ")

輸出

item-0 item-1 item-2 item-3 item-4 item-5 item-6 item-7

輸出顯示上面的程序使用單個線程來說明元素是按照它們插入的順序從隊列中刪除的。

具有多個線程的fifo隊列

為了實現(xiàn)具有多個線程的fifo,我們需要定義myqueue()函數(shù),該函數(shù)從隊列模塊擴(kuò)展。在使用單線程實現(xiàn)fifo隊列時,get()和put()方法的工作與上面討論的相同。然后為了使它成為多線程,我們需要聲明并實例化線程。這些線程將以fifo方式使用隊列。

以下是用于實現(xiàn)具有多個線程的fifo隊列的python程序

import threading
import queue
import random
import time
def myqueue(queue):
   while not queue.empty():
   item = queue.get()
   if item is none:
   break
   print("{} removed {} from the queue".format(threading.current_thread(), item))
   queue.task_done()
   time.sleep(2)
q = queue.queue()
for i in range(5):
   q.put(i)
threads = []
for i in range(4):
   thread = threading.thread(target=myqueue, args=(q,))
   thread.start()
   threads.append(thread)
for thread in threads:
   thread.join()

輸出

 removed 0 from the queue
 removed 1 from the queue
 removed 2 from the queue
 removed 3 from the queue
 removed 4 from the queue

 

lifo,后進(jìn)先出隊列

該隊列使用與fifo(先進(jìn)先出)隊列完全相反的類比。在這個排隊機(jī)制中,最后一個,將首先獲得服務(wù)。這類似于實現(xiàn)堆棧數(shù)據(jù)結(jié)構(gòu)。lifo隊列在實現(xiàn)深度優(yōu)先搜索(如人工智能算法)時非常有用。

python實現(xiàn)lifo隊列

在python中,lifo隊列可以用單線程和多線程實現(xiàn)。

單線程的lifo隊列

為了使用單線程實現(xiàn)lifo隊列, queue 類將使用結(jié)構(gòu) queue .lifoqueue 實現(xiàn)基本的后進(jìn)先出容器?,F(xiàn)在,在調(diào)用 put() 時,元素將添加到容器的頭部,并在使用 get() 時從頭部移除。

以下是用于使用單線程實現(xiàn)lifo隊列的python程序

import queue

q = queue.lifoqueue()

for i in range(8):
   q.put("item-" + str(i))

while not q.empty():
   print (q.get(), end=" ")
output:
item-7 item-6 item-5 item-4 item-3 item-2 item-1 item-0

輸出顯示上述程序使用單個線程來說明元素是按照它們插入的相反順序從隊列中刪除的。

具有多個線程的lifo隊列

實現(xiàn)類似于我們已經(jīng)完成了具有多個線程的fifo隊列的實現(xiàn)。唯一的區(qū)別是我們需要使用 queue 類,它將使用結(jié)構(gòu) queue.lifoqueue 實現(xiàn)基本的 后進(jìn) 先出容器。

以下是用于實現(xiàn)具有多個線程的lifo隊列的python程序 -

import threading
import queue
import random
import time
def myqueue(queue):
   while not queue.empty():
      item = queue.get()
      if item is none:
      break
      print("{} removed {} from the queue".format(threading.current_thread(), item))
      queue.task_done()
      time.sleep(2)
q = queue.lifoqueue()
for i in range(5):
   q.put(i)
threads = []
for i in range(4):
   thread = threading.thread(target=myqueue, args=(q,))
   thread.start()
   threads.append(thread)
for thread in threads:
   thread.join()

輸出

 removed 4 from the queue
 removed 3 from the queue
 removed 2 from the queue
 removed 1 from the queue
 removed 0 from the queue

優(yōu)先隊列

在fifo和lifo隊列中,項目的順序與插入順序有關(guān)。但是,在許多情況下,優(yōu)先級比插入順序更重要。讓我們考慮一個現(xiàn)實世界的例子。假設(shè)機(jī)場的安檢正在檢查不同類別的人??梢詢?yōu)先檢查vvip的人員,航空公司的工作人員,海關(guān)官員,類別,而不是像對于平民那樣在到達(dá)的基礎(chǔ)上進(jìn)行檢查。

優(yōu)先級隊列需要考慮的另一個重要方面是如何開發(fā)任務(wù)調(diào)度程序。一種常見的設(shè)計是在隊列中優(yōu)先處理大多數(shù)代理任務(wù)。此數(shù)據(jù)結(jié)構(gòu)可用于根據(jù)隊列的優(yōu)先級值從隊列中獲取項目。

python優(yōu)先級隊列的實現(xiàn)

在python中,優(yōu)先級隊列可以用單線程和多線程實現(xiàn)。

單線程的優(yōu)先級隊列

為了實現(xiàn)具有單線程的優(yōu)先級隊列, queue 類將使用結(jié)構(gòu) queue .priorityqueue 在優(yōu)先級容器上實現(xiàn)任務(wù)?,F(xiàn)在,在調(diào)用 put() 時,元素將添加一個值,其中最低值將具有最高優(yōu)先級,因此首先使用 get() 檢索。

考慮使用以下python程序?qū)崿F(xiàn)具有單線程的優(yōu)先級隊列

import queue as q
p_queue = q.priorityqueue()

p_queue.put((2, 'urgent'))
p_queue.put((1, 'most urgent'))
p_queue.put((10, 'nothing important'))
prio_queue.put((5, 'important'))

while not p_queue.empty():
   item = p_queue.get()
   print('%s - %s' % item)

輸出

1 – most urgent
2 - urgent
5 - important
10 – nothing important

在上面的輸出中,我們可以看到隊列已經(jīng)根據(jù)優(yōu)先級存儲了項目 - 較少的值具有高優(yōu)先級。

具有多線程的優(yōu)先級隊列

該實現(xiàn)類似于具有多個線程的fifo和lifo隊列的實現(xiàn)。唯一的區(qū)別是我們需要使用 queue 類來使用結(jié)構(gòu) queue.priorityqueue 來初始化優(yōu)先級。另一個區(qū)別在于生成隊列的方式。在下面給出的示例中,將使用兩個相同的數(shù)據(jù)集生成它。

以下python程序有助于實現(xiàn)具有多個線程的優(yōu)先級隊列

import threading
import queue
import random
import time
def myqueue(queue):
   while not queue.empty():
      item = queue.get()
      if item is none:
      break
      print("{} removed {} from the queue".format(threading.current_thread(), item))
      queue.task_done()
      time.sleep(1)
q = queue.priorityqueue()
for i in range(5):
   q.put(i,1)

for i in range(5):
   q.put(i,1)

threads = []
for i in range(2):
   thread = threading.thread(target=myqueue, args=(q,))
   thread.start()
   threads.append(thread)
for thread in threads:
   thread.join()

輸出

 removed 0 from the queue
 removed 0 from the queue
 removed 1 from the queue
 removed 1 from the queue
 removed 2 from the queue
 removed 2 from the queue
 removed 3 from the queue
 removed 3 from the queue
 removed 4 from the queue
 removed 4 from the queue

下一節(jié):python 測試線程應(yīng)用程序

python 并發(fā)簡介

相關(guān)文章