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

Python 同步線程

python 同步線程

線程同步可以被定義為一種方法,借助于該方法,我們可以確保兩個或更多并發(fā)線程不同時訪問稱為臨界區(qū)的程序段。另一方面,正如我們所知,臨界區(qū)是訪問共享資源的程序的一部分。因此,我們可以說同步是通過同時訪問資源來確保兩個或多個線程不相互連接的過程。下圖顯示了四個線程同時嘗試訪問程序的關鍵部分。

為了更清楚,假設有兩個或更多線程試圖同時在列表中添加對象。此行為無法導致成功結束,因為它將丟棄一個或所有對象,否則將完全破壞列表的狀態(tài)。這里同步的作用是一次只有一個線程可以訪問列表。

 

線程同步中的問題

在實現(xiàn)并發(fā)編程或應用同步原語時,我們可能會遇到問題。在本節(jié)中,我們將討論兩個主要問題。問題是

  • deadlock
  • race condition

比賽條件

這是并發(fā)編程中的主要問題之一。對共享資源的并發(fā)訪問可能導致競爭條件。競爭條件可以定義為當兩個或多個線程可以訪問共享數(shù)據(jù)然后嘗試同時更改其值時發(fā)生的條件。因此,變量的值可能是不可預測的,并且取決于過程的上下文切換的定時而變化。

考慮這個例子來理解競爭條件的概念 -

第1步 - 在這一步中,我們需要導入線程模塊 -

import threading

第2步 - 現(xiàn)在,定義一個全局變量,比如x,以及它的值為0 -

x = 0

第3步 - 現(xiàn)在,我們需要定義 increment_global() 函數(shù),它將在此全局函數(shù)x中增加1 -

def increment_global():

   global x
   x += 1

步驟4 - 在這一步中,我們將定義 taskofthread() 函數(shù),該函數(shù)將調用increment_global()函數(shù)指定的次數(shù); 對于我們的例子它是50000次 -

def taskofthread():

   for _ in range(50000):
      increment_global()

步驟5 - 現(xiàn)在,定義main()函數(shù),其中創(chuàng)建了線程t1和t2。 兩者都將在start()函數(shù)的幫助下啟動,并等到他們在join()函數(shù)的幫助下完成工作。

def main():
   global x
   x = 0

   t1 = threading.thread(target= taskofthread)
   t2 = threading.thread(target= taskofthread)

   t1.start()
   t2.start()

   t1.join()
   t2.join()

第6步 - 現(xiàn)在,我們需要給出我們想要調用main()函數(shù)的迭代次數(shù)的范圍。 在這里,我們稱它為5次。

if __name__ == "__main__":
   for i in range(5):
      main()
      print("x = {1} after iteration {0}".format(i,x))

在下面顯示的輸出中,我們可以看到競爭條件的影響,因為每次迭代后x的值預計為100000.但是,值有很多變化。這是由于線程并發(fā)訪問共享全局變量x。

輸出

x = 100000 after iteration 0
x = 54034 after iteration 1
x = 80230 after iteration 2
x = 93602 after iteration 3
x = 93289 after iteration 4

 

使用鎖處理競爭條件

正如我們在上面的程序中看到競爭條件的影響,我們需要一個同步工具,它可以處理多個線程之間的競爭條件。在python中, 模塊提供了lock類來處理競爭條件。此外, lock 類提供了不同的方法,我們可以幫助處理多個線程之間的競爭條件。方法如下所述

acquire()方法

該方法用于獲取,即阻止鎖定。鎖定可以是阻塞或非阻塞,具體取決于以下真值或假值

  • 將值設置為true - 如果使用true(默認參數(shù))調用acquire()方法,則會阻止線程執(zhí)行,直到解鎖為止。

  • 將值設置為false - 如果使用false調用acquire()方法(這不是默認參數(shù)),則在將其設置為true(即直到鎖定)之前,不會阻止線程執(zhí)行。

release()方法

此方法用于釋放鎖定。以下是與此方法相關的一些重要任務

  • 如果鎖被鎖定,那么 release() 方法將解鎖它。它的工作是,如果多個線程被阻塞并等待鎖解鎖,則只允許一個線程繼續(xù)運行。

  • 如果鎖已經解鎖,它將引發(fā) threaderror 。

現(xiàn)在,我們可以使用lock類及其方法重寫上述程序,以避免競爭條件。我們需要使用lock參數(shù)定義taskofthread()方法,然后需要使用acquire()和release()方法來阻止和非阻塞鎖以避免競爭條件。

以下是了解用于處理競爭條件的鎖概念的python程序示例 -

import threading

x = 0

def increment_global():

   global x
   x += 1

def taskofthread(lock):

   for _ in range(50000):
      lock.acquire()
      increment_global()
      lock.release()

def main():
   global x
   x = 0

   lock = threading.lock()
   t1 = threading.thread(target = taskofthread, args = (lock,))
   t2 = threading.thread(target = taskofthread, args = (lock,))

   t1.start()
   t2.start()

   t1.join()
   t2.join()

if __name__ == "__main__":
   for i in range(5):
      main()
      print("x = {1} after iteration {0}".format(i,x))

以下輸出表明忽略了競爭條件的影響; 因為x的值,在每次迭代之后,現(xiàn)在是100000,這符合該程序的期望。

輸出

x = 100000 after iteration 0
x = 100000 after iteration 1
x = 100000 after iteration 2
x = 100000 after iteration 3
x = 100000 after iteration 4

 

死鎖 - 餐飲哲學家的問題

死鎖是設計并發(fā)系統(tǒng)時可能遇到的麻煩問題。我們可以借助餐飲哲學家的問題來說明這個問題如下 -

edsger dijkstra最初介紹了餐飲哲學家的問題,其中一個著名的插圖是并發(fā)系統(tǒng)中最大的問題之一,稱為死鎖。

在這個問題上,有五位著名的哲學家坐在圓桌旁,從他們的碗里吃一些食物。五個哲學家可以使用五把叉來吃他們的食物。然而,哲學家們決定同時使用兩把叉來吃他們的食物。

現(xiàn)在,哲學家有兩個主要條件。首先,每個哲學家可以處于進食狀態(tài)或處于思維狀態(tài),其次,他們必須首先獲得兩個分叉,即左右分支。當五位哲學家中的每一位都設法同時選擇左叉時,問題就出現(xiàn)了?,F(xiàn)在他們都在等待正確的叉子自由,但他們永遠不會放棄他們的叉子,直到他們吃了他們的食物并且正確的叉子永遠不可用。因此,餐桌上會出現(xiàn)死鎖狀態(tài)。

并發(fā)系統(tǒng)中的死鎖

現(xiàn)在,如果我們看到,我們的并發(fā)系統(tǒng)也會出現(xiàn)同樣的問題。上例中的分支將是系統(tǒng)資源,每個哲學家都可以代表競爭獲取資源的過程。

使用python程序解決方案

通過將哲學家分為兩類 - 貪婪的哲學家 和 慷慨的哲學家, 可以找到這個問題的解決方案。主要是一個貪婪的哲學家將嘗試拿起左叉并等到它在那里。然后他會等待正確的叉子在那里,撿起來吃,然后把它放下。另一方面,一個慷慨的哲學家會試圖拿起左叉,如果不存在,他會等一段時間再試一次。如果他們得到左叉,那么他們會嘗試找到合適的叉子。如果他們也會獲得正確的叉子,那么他們就會吃掉并釋放兩個叉子。但是,如果他們不能獲得正確的分叉,那么他們將釋放左分叉。

以下python程序將幫助我們找到餐飲哲學家問題的解決方案

import threading
import random
import time

class diningphilosopher(threading.thread):

   running = true

   def __init__(self, xname, leftfork, rightfork):
   threading.thread.__init__(self)
   self.name = xname
   self.leftfork = leftfork
   self.rightfork = rightfork

   def run(self):
   while(self.running):
      time.sleep( random.uniform(3,13))
      print ('%s is hungry.' % self.name)
      self.dine()

   def dine(self):
   fork1, fork2 = self.leftfork, self.rightfork

   while self.running:
      fork1.acquire(true)
      locked = fork2.acquire(false)
      if locked: break
      fork1.release()
      print ('%s swaps forks' % self.name)
      fork1, fork2 = fork2, fork1
   else:
      return

   self.dining()
   fork2.release()
   fork1.release()

   def dining(self):
   print ('%s starts eating '% self.name)
   time.sleep(random.uniform(1,10))
   print ('%s finishes eating and now thinking.' % self.name)

def dining_philosophers():
   forks = [threading.lock() for n in range(5)]
   philosophernames = ('1st','2nd','3rd','4th', '5th')

   philosophers= [diningphilosopher(philosophernames[i], forks[i%5], forks[(i+1)%5]) \
      for i in range(5)]

   random.seed()
   diningphilosopher.running = true
   for p in philosophers: p.start()
   time.sleep(30)
   diningphilosopher.running = false
   print (" it is finishing.")

dining_philosophers()

上述計劃使用了貪婪和慷慨的哲學家的概念。該程序還使用了 < threading>模塊的 lock 類的 acquire() 和 release() 方法。我們可以在以下輸出中看到解決方案

輸出

4th is hungry.
4th starts eating
1st is hungry.
1st starts eating
2nd is hungry.
5th is hungry.
3rd is hungry.
1st finishes eating and now thinking.3rd swaps forks
2nd starts eating
4th finishes eating and now thinking.
3rd swaps forks5th starts eating
5th finishes eating and now thinking.
4th is hungry.
4th starts eating
2nd finishes eating and now thinking.
3rd swaps forks
1st is hungry.
1st starts eating
4th finishes eating and now thinking.
3rd starts eating
5th is hungry.
5th swaps forks
1st finishes eating and now thinking.
5th starts eating
2nd is hungry.
2nd swaps forks
4th is hungry.
5th finishes eating and now thinking.
3rd finishes eating and now thinking.
2nd starts eating 4th starts eating
it is finishing.

下一節(jié):python 線程通信

相關文章