最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

處理python中多線程與多進(jìn)程中的數(shù)據(jù)共享問題

 更新時間:2019年07月28日 08:47:53   作者:楊彥星  
這篇文章主要介紹了python中多線程與多進(jìn)程中的數(shù)據(jù)共享問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

之前在寫多線程與多進(jìn)程的時候,因?yàn)橐话闱闆r下都是各自完成各自的任務(wù),各個子線程或者各個子進(jìn)程之前并沒有太多的聯(lián)系,如果需要通信的話我會使用隊(duì)列或者數(shù)據(jù)庫來完成,但是最近我在寫一些多線程與多進(jìn)程的代碼時,發(fā)現(xiàn)如果它們需要用到共享變量的話,需要有一些注意的地方

多線程之間的共享數(shù)據(jù)

標(biāo)準(zhǔn)數(shù)據(jù)類型在線程間共享

看以下代碼

#coding:utf-8
import threading
def test(name,data):
  print("in thread {} name is {}".format(threading.current_thread(),name))
  print("data is {} id(data) is {}".format(data,id(data)))
if __name__ == '__main__':
  d = 5
  name = "楊彥星"
  for i in range(5):
    th = threading.Thread(target=test,args=(name,d))
    th.start()

這里我創(chuàng)建一個全局的int變量d,它的值是5,當(dāng)我在5個線程中調(diào)用test函數(shù)時,將d作為參數(shù)傳進(jìn)去,那么這5個線程所擁有的是同一個d嗎?我在test函數(shù)中通過 id(data) 來打印一下它們的ID,得到了如下的結(jié)果

in thread <Thread(Thread-1, started 6624)> name is 楊彥星
data is 5 id(data) is 1763791776
in thread <Thread(Thread-2, started 8108)> name is 楊彥星
data is 5 id(data) is 1763791776
in thread <Thread(Thread-3, started 3356)> name is 楊彥星
data is 5 id(data) is 1763791776
in thread <Thread(Thread-4, started 13728)> name is 楊彥星
data is 5 id(data) is 1763791776
in thread <Thread(Thread-5, started 3712)> name is 楊彥星
data is 5 id(data) is 1763791776

從結(jié)果中可以看到,在5個子線程中,data的id都是1763791776,說明在主線程中創(chuàng)建了變量d,在子線程中是可以共享的,在子線程中對共享元素的改變是會影響到其它線程的,所以如果要對共享變量進(jìn)行修改時,也就是線程不安全的,需要加鎖。

自定義類型對象在線程間共享

如果我們要自定義一個類呢,將一個對象作為變量在子線程中傳遞呢?會是什么效果呢?

#coding:utf-8
import threading
class Data:
  def __init__(self,data=None):
    self.data = data
  def get(self):
    return self.data
  def set(self,data):
    self.data = data
def test(name,data):
  print("in thread {} name is {}".format(threading.current_thread(),name))
  print("data is {} id(data) is {}".format(data.get(),id(data)))
if __name__ == '__main__':
  d = Data(10)
  name = "楊彥星"
  print("in main thread id(data) is {}".format(id(d)))
  for i in range(5):
    th = threading.Thread(target=test,args=(name,d))
    th.start()

這里我定義一個簡單的類,在主線程初始化了一個該類型的對象d,然后將它作為參數(shù)傳給子線程,主線程和子線程分別打印了這個對象的id,我們來看一下結(jié)果

in main thread id(data) is 2849240813864
in thread <Thread(Thread-1, started 11648)> name is 楊彥星
data is 10 id(data) is 2849240813864
in thread <Thread(Thread-2, started 11016)> name is 楊彥星
data is 10 id(data) is 2849240813864
in thread <Thread(Thread-3, started 10416)> name is 楊彥星
data is 10 id(data) is 2849240813864
in thread <Thread(Thread-4, started 8668)> name is 楊彥星
data is 10 id(data) is 2849240813864
in thread <Thread(Thread-5, started 4420)> name is 楊彥星
data is 10 id(data) is 2849240813864

我們看到,在主線程和子線程中,這個對象的id是一樣的,說明它們用的是同一個對象。

無論是標(biāo)準(zhǔn)數(shù)據(jù)類型還是復(fù)雜的自定義數(shù)據(jù)類型,它們在多線程之間是共享同一個的,但是在多進(jìn)程中是這樣的嗎?

多進(jìn)程之間的共享數(shù)據(jù)

標(biāo)準(zhǔn)數(shù)據(jù)類型在進(jìn)程間共享

還是上面的代碼,我們先來看一下int類型的變量的子進(jìn)程間的共享

#coding:utf-8
import threading
import multiprocessing
def test(name,data):
  print("in thread {} name is {}".format(threading.current_thread(),name))
  print("data is {} id(data) is {}".format(data,id(data)))
if __name__ == '__main__':
  d = 10
  name = "楊彥星"
  print("in main thread id(data) is {}".format(id(d)))
  for i in range(5):
    pro = multiprocessing.Process(target=test,args=(name,d))
    pro.start()

得到的結(jié)果是

in main thread id(data) is 1763791936
in thread <_MainThread(MainThread, started 9364)> name is 楊彥星
data is 10 id(data) is 1763791936
in thread <_MainThread(MainThread, started 9464)> name is 楊彥星
data is 10 id(data) is 1763791936
in thread <_MainThread(MainThread, started 3964)> name is 楊彥星
data is 10 id(data) is 1763791936
in thread <_MainThread(MainThread, started 10480)> name is 楊彥星
data is 10 id(data) is 1763791936
in thread <_MainThread(MainThread, started 13608)> name is 楊彥星
data is 10 id(data) is 1763791936

可以看到它們的id是一樣的,說明用的是同一個變量,但是當(dāng)我嘗試把d由int變?yōu)榱藄tring時,發(fā)現(xiàn)它們又不一樣了……

if __name__ == '__main__':
  d = 'yangyanxing'
  name = "楊彥星"
  print("in main thread id(data) is {}".format(id(d)))
  for i in range(5):
    pro = multiprocessing.Process(target=test,args=(name,d))
    pro.start()

此時得到的結(jié)果是

in main thread id(data) is 2629633397040
in thread <_MainThread(MainThread, started 9848)> name is 楊彥星
data is yangyanxing id(data) is 1390942032880
in thread <_MainThread(MainThread, started 988)> name is 楊彥星
data is yangyanxing id(data) is 2198251377648
in thread <_MainThread(MainThread, started 3728)> name is 楊彥星
data is yangyanxing id(data) is 2708672287728
in thread <_MainThread(MainThread, started 5288)> name is 楊彥星
data is yangyanxing id(data) is 2376058999792
in thread <_MainThread(MainThread, started 12508)> name is 楊彥星
data is yangyanxing id(data) is 2261044040688

于是我又嘗試了list、Tuple、dict,結(jié)果它們都是不一樣的,我又回過頭來試著在多線程中使用列表元組和字典,結(jié)果它們還是一樣的。

這里有一個有趣的問題,如果是int類型,當(dāng)值小于等于256時,它們在多進(jìn)程間的id是相同的,如果大于256,則它們的id就會不同了,這個我沒有查看原因。

自定義類型對象在進(jìn)程間共享

#coding:utf-8
import threading
import multiprocessing
class Data:
  def __init__(self,data=None):
    self.data = data
  def get(self):
    return self.data
  def set(self,data):
    self.data = data
def test(name,data):
  print("in thread {} name is {}".format(threading.current_thread(),name))
  print("data is {} id(data) is {}".format(data.get(),id(data)))

if __name__ == '__main__':
  d = Data(10)
  name = "楊彥星"
  print("in main thread id(data) is {}".format(id(d)))
  for i in range(5):
    pro = multiprocessing.Process(target=test,args=(name,d))
    pro.start()

得到的結(jié)果是

in main thread id(data) is 1927286591728
in thread <_MainThread(MainThread, started 2408)> name is 楊彥星
data is 10 id(data) is 1561177927752
in thread <_MainThread(MainThread, started 5728)> name is 楊彥星
data is 10 id(data) is 2235260514376
in thread <_MainThread(MainThread, started 1476)> name is 楊彥星
data is 10 id(data) is 2350586073040
in thread <_MainThread(MainThread, started 996)> name is 楊彥星
data is 10 id(data) is 2125002248088
in thread <_MainThread(MainThread, started 10740)> name is 楊彥星
data is 10 id(data) is 1512231669656

可以看到它們的id是不同的,也就是不同的對象。

在多進(jìn)程間如何共享數(shù)據(jù)

我們看到,數(shù)據(jù)在多進(jìn)程間是不共享的(小于256的int類型除外),但是我們又想在主進(jìn)程和子進(jìn)程間共享一個數(shù)據(jù)對象時該如何操作呢?

在看這個問題之前,我們先將之前的多線程代碼做下修改

#coding:utf-8
import threading
import multiprocessing
class Data:
  def __init__(self,data=None):
    self.data = data
  def get(self):
    return self.data
  def set(self,data):
    self.data = data
def test(name,data,lock):
  lock.acquire()
  print("in thread {} name is {}".format(threading.current_thread(),name))
  print("data is {} id(data) is {}".format(data,id(data)))
  data.set(data.get()+1)
  lock.release()
if __name__ == '__main__':
  d = Data(0)
  thlist = []
  name = "yang"
  lock = threading.Lock()
  for i in range(5):
    th = threading.Thread(target=test,args=(name,d,lock))
    th.start()
    thlist.append(th)
  for i in thlist:
    i.join()
  print(d.get())

我們這個代碼的目的是這樣,使用自定義的Data類型對象,當(dāng)經(jīng)過5個子線程操作以后,每個子線程對其data值進(jìn)行加1操作,最后在主線程打印對象的data值。

該輸出結(jié)果如下

in thread <Thread(Thread-1, started 3296)> name is yang
data is <__main__.Data object at 0x000001A451139198> id(data) is 1805246501272
in thread <Thread(Thread-2, started 9436)> name is yang
data is <__main__.Data object at 0x000001A451139198> id(data) is 1805246501272
in thread <Thread(Thread-3, started 760)> name is yang
data is <__main__.Data object at 0x000001A451139198> id(data) is 1805246501272
in thread <Thread(Thread-4, started 1952)> name is yang
data is <__main__.Data object at 0x000001A451139198> id(data) is 1805246501272
in thread <Thread(Thread-5, started 5988)> name is yang
data is <__main__.Data object at 0x000001A451139198> id(data) is 1805246501272

可以看到在主線程最后打印出來了5,符合我們的預(yù)期,但是如果放到多進(jìn)程中呢?因?yàn)槎噙M(jìn)程下,每個子進(jìn)程所持有的對象是不同的,所以每個子進(jìn)程操作的是各自的Data對象,對于主進(jìn)程的Data對象應(yīng)該是沒有影響的,我們來看下它的結(jié)果

#coding:utf-8
import threading
import multiprocessing
class Data:
  def __init__(self,data=None):
    self.data = data
  def get(self):
    return self.data
  def set(self,data):
    self.data = data
def test(name,data,lock):
  lock.acquire()
  print("in thread {} name is {}".format(threading.current_thread(),name))
  print("data is {} id(data) is {}".format(data,id(data)))
  data.set(data.get()+1)
  lock.release()
if __name__ == '__main__':
  d = Data(0)
  thlist = []
  name = "yang"
  lock = multiprocessing.Lock()
  for i in range(5):
    th = multiprocessing.Process(target=test,args=(name,d,lock))
    th.start()
    thlist.append(th)
  for i in thlist:
    i.join()
  print(d.get())

它的輸出結(jié)果是:

in thread <_MainThread(MainThread, started 7604)> name is yang
data is <__mp_main__.Data object at 0x000001D110130EB8> id(data) is 1997429477048
in thread <_MainThread(MainThread, started 12108)> name is yang
data is <__mp_main__.Data object at 0x000002C4E88E0E80> id(data) is 3044738469504
in thread <_MainThread(MainThread, started 3848)> name is yang
data is <__mp_main__.Data object at 0x0000027827270EF0> id(data) is 2715076202224
in thread <_MainThread(MainThread, started 12368)> name is yang
data is <__mp_main__.Data object at 0x000002420EA80E80> id(data) is 2482736991872
in thread <_MainThread(MainThread, started 4152)> name is yang
data is <__mp_main__.Data object at 0x000001B1577F0E80> id(data) is 1861188783744

最后的輸出是0,說明了子進(jìn)程對于主進(jìn)程傳入的Data對象操作其實(shí)對于主進(jìn)程的對象是不起作用的,我們需要怎樣的操作才能實(shí)現(xiàn)子進(jìn)程可以操作主進(jìn)程的對象呢?我們可以使用 multiprocessing.managers 下的 BaseManager 來實(shí)現(xiàn)

#coding:utf-8
import threading
import multiprocessing
from multiprocessing.managers import BaseManager
class Data:
  def __init__(self,data=None):
    self.data = data
  def get(self):
    return self.data
  def set(self,data):
    self.data = data
BaseManager.register("mydata",Data)
def test(name,data,lock):
  lock.acquire()
  print("in thread {} name is {}".format(threading.current_thread(),name))
  print("data is {} id(data) is {}".format(data,id(data)))
  data.set(data.get()+1)
  lock.release()
def getManager():
  m = BaseManager()
  m.start()
  return m
if __name__ == '__main__':
  manager = getManager()
  d = manager.mydata(0)
  thlist = []
  name = "yang"
  lock = multiprocessing.Lock()
  for i in range(5):
    th = multiprocessing.Process(target=test,args=(name,d,lock))
    th.start()
    thlist.append(th)
  for i in thlist:
    i.join()
  print(d.get())

使用 from multiprocessing.managers import BaseManager 引入 BaseManager以后,在定義完Data類型之后,使用 BaseManager.register("mydata",Data) 將Data類型注冊到BaseManager中,并且給了它一個名字叫 mydata ,之后就可以使用 BaseManager 對象的這個名字來初始化對象,我們來看一下輸出

C:\Python35\python.exe F:/python/python3Test/multask.py
in thread <_MainThread(MainThread, started 12244)> name is yang
data is <__mp_main__.Data object at 0x000001FE1B7D9668> id(data) is 2222932504080
in thread <_MainThread(MainThread, started 2860)> name is yang
data is <__mp_main__.Data object at 0x000001FE1B7D9668> id(data) is 1897574510096
in thread <_MainThread(MainThread, started 2748)> name is yang
data is <__mp_main__.Data object at 0x000001FE1B7D9668> id(data) is 2053415775760
in thread <_MainThread(MainThread, started 7812)> name is yang
data is <__mp_main__.Data object at 0x000001FE1B7D9668> id(data) is 2766155820560
in thread <_MainThread(MainThread, started 2384)> name is yang
data is <__mp_main__.Data object at 0x000001FE1B7D9668> id(data) is 2501159890448

我們看到,雖然在每個子進(jìn)程中使用的是不同的對象,但是它們的值卻是可以“共享”的。

標(biāo)準(zhǔn)的數(shù)據(jù)類型也可以通過multiprocessing庫中的Value對象,舉一個簡單的例子

#coding:utf-8
import threading
import multiprocessing
from multiprocessing.managers import BaseManager
class Data:
  def __init__(self,data=None):
    self.data = data
  def get(self):
    return self.data
  def set(self,data):
    self.data = data
BaseManager.register("mydata",Data)
def test(name,data,lock):
  lock.acquire()
  print("in thread {} name is {}".format(threading.current_thread(),name))
  print("data is {} id(data) is {}".format(data,id(data)))
  data.value +=1
  lock.release()
if __name__ == '__main__':
  d = multiprocessing.Value("l",10) #
  print(d)
  thlist = []
  name = "yang"
  lock = multiprocessing.Lock()
  for i in range(5):
    th = multiprocessing.Process(target=test,args=(name,d,lock))
    th.start()
    thlist.append(th)
  for i in thlist:
    i.join()
  print(d.value)

這里使用 d = multiprocessing.Value("l",10) 初始化了一個數(shù)字類型的對象,這個類型是 Synchronized wrapper for c_long , multiprocessing.Value 在初始化時,第一個參數(shù)是類型,第二個參數(shù)是值,具體支持的類型如下

還可以使用ctypes庫里和類初始化字符串

>>> from ctypes import c_char_p
>>> s = multiprocessing.Value(c_char_p, b'\xd1\xee\xd1\xe5\xd0\xc7')
>>> print(s.value.decode('gbk'))

楊彥星

還可以使用Manager對象初始list,dict等

#coding:utf-8
import multiprocessing
def func(mydict, mylist):
  # 子進(jìn)程改變dict,主進(jìn)程跟著改變
  mydict["index1"] = "aaaaaa" 
  # 子進(jìn)程改變List,主進(jìn)程跟著改變 
  mydict["index2"] = "bbbbbb"
  mylist.append(11) 
  mylist.append(22)
  mylist.append(33)
if __name__ == "__main__":
  # 主進(jìn)程與子進(jìn)程共享這個字典
  mydict = multiprocessing.Manager().dict()
  # 主進(jìn)程與子進(jìn)程共享這個List
  mylist = multiprocessing.Manager().list(range(5)) 
  p = multiprocessing.Process(target=func, args=(mydict, mylist))
  p.start()
  p.join()
  print(mylist)
  print(mydict)

其實(shí)我們這里所說的共享只是數(shù)據(jù)值上的共享,因?yàn)樵诙噙M(jìn)程中,各自持有的對象都不相同,所以如果想要同步狀態(tài)需要曲線救國。不過這種在自己寫的小項(xiàng)目中可以簡單的使用,如果做一些大一點(diǎn)的項(xiàng)目,還是建議不要使用這種共享數(shù)據(jù)的方式,這種大大的增加了程序間的耦合性,使用邏輯變得復(fù)雜難懂,所以建議還是使用隊(duì)列或者數(shù)據(jù)為進(jìn)行間通信的渠道。

總結(jié)

以上所述是小編給大家介紹的處理python中多線程與多進(jìn)程中的數(shù)據(jù)共享問題,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!

相關(guān)文章

  • 關(guān)于pytorch處理類別不平衡的問題

    關(guān)于pytorch處理類別不平衡的問題

    今天小編就為大家分享一篇關(guān)于pytorch處理類別不平衡的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • python自動化測試工具Helium使用示例

    python自動化測試工具Helium使用示例

    大家好,本篇文章主要講的是python自動化測試工具Helium使用示例,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下哦
    2021-12-12
  • 10分鐘學(xué)會使用python實(shí)現(xiàn)人臉識別(附源碼)

    10分鐘學(xué)會使用python實(shí)現(xiàn)人臉識別(附源碼)

    這篇文章主要介紹了10分鐘學(xué)會使用python實(shí)現(xiàn)人臉識別(附源碼),幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-03-03
  • Python之split函數(shù)的深入理解

    Python之split函數(shù)的深入理解

    split函數(shù)主要應(yīng)用場景是Python對字符串的處理中(數(shù)據(jù)分析,數(shù)據(jù)處理),以及計(jì)算機(jī)二級考試的??蓟A(chǔ)知識點(diǎn),這篇文章主要介紹了Python之split函數(shù)的詳解,需要的朋友可以參考下
    2023-02-02
  • 解決jupyter notebook 出現(xiàn)In[*]的問題

    解決jupyter notebook 出現(xiàn)In[*]的問題

    這篇文章主要介紹了解決jupyter notebook 出現(xiàn)In[*]的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • Python二進(jìn)制轉(zhuǎn)化為十進(jìn)制數(shù)學(xué)算法詳解

    Python二進(jìn)制轉(zhuǎn)化為十進(jìn)制數(shù)學(xué)算法詳解

    這篇文章主要介紹了Python二進(jìn)制轉(zhuǎn)化為十進(jìn)制數(shù)學(xué)算法,同時在這里也給大家分享一個好用的內(nèi)置函數(shù)map(),需要的朋友可以參考下
    2023-01-01
  • tensorflow 環(huán)境變量設(shè)置方式

    tensorflow 環(huán)境變量設(shè)置方式

    今天小編就為大家分享一篇tensorflow 環(huán)境變量設(shè)置方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • Python實(shí)現(xiàn)發(fā)送郵件到自己郵箱

    Python實(shí)現(xiàn)發(fā)送郵件到自己郵箱

    在日常開發(fā)中,我們經(jīng)常需要監(jiān)控應(yīng)用程序的狀態(tài),及時發(fā)現(xiàn)問題并采取措施解決。而通過郵件發(fā)送報(bào)警信息則是一種常見的實(shí)現(xiàn)方式。本文就來介紹一下Python實(shí)現(xiàn)發(fā)送郵件到自己郵箱的方法
    2023-04-04
  • Python處理RSS、ATOM模塊FEEDPARSER介紹

    Python處理RSS、ATOM模塊FEEDPARSER介紹

    這篇文章主要介紹了Python處理RSS、ATOM模塊FEEDPARSER介紹,本文只是做個入門級的簡潔介紹,需要的朋友可以參考下
    2015-02-02
  • Python OpenCV圖像復(fù)原的實(shí)現(xiàn)步驟

    Python OpenCV圖像復(fù)原的實(shí)現(xiàn)步驟

    Python OpenCV圖像復(fù)原是一個涉及去除噪聲、模糊等失真的過程,旨在恢復(fù)圖像的原始質(zhì)量,以下是一個詳細(xì)的案例教程,包括理論背景和具體實(shí)現(xiàn)步驟,需要的朋友可以參考下
    2024-12-12

最新評論

望城县| 潼南县| 中山市| 博白县| 佳木斯市| 伊吾县| 绥芬河市| 江油市| 屏东县| 房山区| 九江市| 江油市| 石景山区| 榆林市| 常山县| 岑溪市| 科尔| 昌图县| 贵定县| 武义县| 沁水县| 平塘县| 铜梁县| 宝丰县| 廉江市| 横峰县| 历史| 大埔区| 汉川市| 海安县| 元氏县| 东乡县| 克什克腾旗| 巫山县| 浦北县| 乾安县| 合川市| 五家渠市| 西盟| 贞丰县| 伊宁县|