python multiprocessing多進程變量共享與加鎖的實現

 更新時間:2019年10月02日 10:00:12   作者:京醬玫瑰   我要評論
這篇文章主要介紹了python multiprocessing多進程變量共享與加鎖的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

python多進程和多線程是大家會重點了解的部分,因為很多工作如果并沒有前后相互依賴關系的話其實順序并不是非常的重要,采用順序執行的話就必定會造成無謂的等待,任憑cpu和內存白白浪費,這是我們不想看到的。

為了解決這個問題,我們就可以采用多線程或者多進程的方式,(多線程我們之后再講),而這兩者之間是有本質區別的。就內存而言,已知進程是在執行過程中有獨立的內存單元的,而多個線程是共享內存的,這是多進程和多線程的一大區別。

利用Value在不同進程中同步變量

在多進程中,由于進程之間內存相互是隔離的,所以無法在多個進程中用直接讀取的方式共享變量,這時候就可以用multiprocessing庫中的 Value在各自隔離的進程中共享變量。

下面是一個多進程的例子:

假設有一個counter用來記錄程序經過的總循環次數,每調用一次count函數之后counter就會增加20,在主程序中用循環開10個進程分別調用count函數,那么理想狀態下,在十個進程中共享的counter值到程序結束后應該是200。

from multiprocessing import Process, Value
import time

def count(v):
  for i in range(20):
    time.sleep(0.01)
    v.value += 1

def main():
  value = Value('i',0)
  processes = [Process(target=count, args=(value,)) for i in range(10)]

  for p in processes:
    p.start()
  for p in processes:
    p.join()

  print(value.value)

if __name__ == '__main__':

  for i in range(10):
    main()

運行這個例子,會得到怎樣的結果呢?

188
180
168
186
183
179
186
181
166
186

我在主程序里運行了十次這個程序,而最后的結果是160-180之間,總之,沒有一次到200。這是什么原因呢?

相信很多人都已經明白了問題所在,那就是因為在multiprocessing庫中的Value是細粒度的,Value中有一個ctypes類型的對象,擁有一個value屬性來表征內存中實際的對象。Value可以保證同時只有一個單獨的線程或進程在讀或者寫value值。這么看起來沒有什么問題。

然而在第一個進程加載value值的時候,程序卻不能阻止第二個進程加載舊的值。兩個進程都會把value拷貝到自己的私有內存然后進行處理,并寫回到共享值里。

那么這么會出現什么問題呢?

最后的共享值只接收到了一次值的增加,而非兩次。

利用Lock在不同進程共享變量時加鎖

上面的問題其實可以用一個非常簡單的方法解決,我們只需要調用multiprocessing庫中的Lock (鎖)就可以保證一次只能有一個進程訪問這個共享變量。修改后的代碼如下:

from multiprocessing import Process, Value, Lock
from time import sleep

def count(x,lock):
  for i in range(20):
    sleep(0.01)
    with lock:
      x.value += 1


def main():
  counter = Value('i',0)
  lock = Lock()
  processes = [Process(target=count,args=(counter,lock)) for i in range(10)]
  for p in processes:
    p.start()
  for p in processes:
    p.join()

  print(counter.value)

if __name__ == '__main__':
  for i in range(10):
    main()

這樣一來,輸出的結果就會恒定為200了。

一些補充

1. 調用get_lock() 函數

其實Value這個包里已經包含了鎖的概念,如果調用get_lock() 函數就可以自動給共享變量加鎖。這樣其實是比較推薦的方式,因為這樣就不需要同時調用兩個包。修改如下:

from multiprocessing import Process, Value
from time import sleep

def count(x):
  for i in range(20):
    global counter # 聲明全局變量
    sleep(0.01)
    with counter.get_lock(): # 直接調用get_lock()函數獲取鎖
      x.value += 1

def main():
  processes = [Process(target=count, args=(counter,)) for i in range(10)]
  for p in processes:
    p.start()
  for p in processes:
    p.join()

  print(counter.value)

if __name__ == '__main__':
  counter = Value('i', 0) # 需要把全局變量移到主程序
  main()

上面的程序更加明確,且最終結果也是200。

2. 使用 multiprocessing.RawValue

整個multiprocessing包里剛剛調用的Value和Lock還可以統一被 multiprocessing.RawValue取代。

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

相關文章

  • Python 多線程其他屬性以及繼承Thread類詳解

    Python 多線程其他屬性以及繼承Thread類詳解

    這篇文章主要介紹了Python 多線程其他屬性以及繼承Thread類詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-08-08
  • Python 實現子類獲取父類的類成員方法

    Python 實現子類獲取父類的類成員方法

    今天小編就為大家分享一篇Python 實現子類獲取父類的類成員方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • Python PyQt4實現QQ抽屜效果

    Python PyQt4實現QQ抽屜效果

    這篇文章主要為大家詳細介紹了Python PyQt4實現QQ抽屜效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • 理解Python垃圾回收機制

    理解Python垃圾回收機制

    這篇文章主要為大家詳細介紹了Python垃圾回收機制,Python中的垃圾回收以引用計數為主,分代收集為輔,想要深入理解Python垃圾回收機制,請閱讀下文
    2016-02-02
  • django創建最簡單HTML頁面跳轉方法

    django創建最簡單HTML頁面跳轉方法

    今天小編就為大家分享一篇django創建最簡單HTML頁面跳轉方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • django框架用戶權限中的session緩存到redis中的方法

    django框架用戶權限中的session緩存到redis中的方法

    今天小編就為大家分享一篇django框架用戶權限中的session緩存到redis中的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • python實現大文本文件分割

    python實現大文本文件分割

    這篇文章主要為大家詳細介紹了python實現大文本文件分割,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • 詳解Python字典的操作

    詳解Python字典的操作

    在本文里小編給大家整理了關于Python字典的相關知識點以及操作方式,有興趣的朋友們學習下。
    2019-03-03
  • python開發之thread實現布朗運動的方法

    python開發之thread實現布朗運動的方法

    這篇文章主要介紹了python開發之thread實現布朗運動的方法,實例分析了Python基于多線程實現繪圖的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11
  • 對python中list的拷貝與numpy的array的拷貝詳解

    對python中list的拷貝與numpy的array的拷貝詳解

    今天小編就為大家分享一篇對python中list的拷貝與numpy的array的拷貝詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01

最新評論

润升娱乐