python學習筆記——多線程同步問題

來源:互聯網
上載者:User

如果多個線程共同對某個資料修改,則可能出現不可預料的結果,為了保證資料的正確性,需要對多個線程進行同步。

1 簡單的線程同步。

  使用Thread對象的Lock和Rlock可以實現簡單的線程同步,這兩個對象都有acquire方法和release方法,對於那些需要每次只允許一個線程操作的資料,可以將其操作放到acquire和release方法之間。如下:

import threading

import time

class mythread(threading.Thread):

    def__init__(self,threadname):

       threading.Thread.__init__(self,name=threadname)

    defrun(self):

       global x

       lock.acquire()

       for i in range(3):

           x=x+1

       time.sleep(2)

       print x

       lock.release()

lock=threading.RLock()

t1=[]

for i in range(10):

   t=mythread(str(i))

   t1.append(t)

x=0

for i in t1:

i.start()

運行結果如下:

>>> 3

6

9

12

15

18

21

24

27

30

 

>>> 

   而如果我們把acquire()和release()去掉,結果就不同了:

30303030303030303030

   這是因為每個線程執行後在列印出x之前都要休眠2秒鐘,所以在這個過程中,每個線程都被執行了,所以等到休眠結束,列印出的X的值自然就是經過多次運算以後的X的值了。

而第一次,我們把全域變數X放到了acquire()和release()之間,python解譯器每次回只允許一個線程對x進行操作,只有這個線程結束對其操作並且休眠結束列印出來以後,才允許下一個線程對x操作,所以輸出的X是每次遞增的,而且用時間也是比較長的。

 

2 使用條件變數保持線程同步

   Python的Condition對象提供了對複雜線程同步的支援,使用它可以在某些事件觸發之後才處理資料,condition的方法有很多,看下面的例子:

用Condition來實現著名的生產者和消費者的關係:

import threading

class Producer(threading.Thread):

    def__init__(self,threadname):

       threading.Thread.__init__(self,name=threadname)

    defrun(self):

       global x

       con.acquire()

       if x==1000000:

           con.wait()

           pass

       else:

           for i in range(1000000):

               x=x+1

           con.notify()

       print x

       con.release()

 

class Consumer(threading.Thread):

    def__init__(self,threadname):

       threading.Thread.__init__(self,name=threadname)

    defrun(self):

       global x

       con.acquire()

       if x==0:

           con.wait()

           pass

       else:

           for i in range(1000000):

               x=x-1

           con.notify()

       print x

       con.release()

con=threading.Condition()

x=0

p=Producer('Producer')

c=Consumer('Consumer')

p.start()

c.start()

p.join()

c.join()

print x

 

結果如下:

>>>

1000000

0

0

>>> 

 

3 使用隊列保持線程同步

   同樣的例子,使用Queue可以實現多生產者和多消費者的先進先出的隊列,每個生產者將資料依次存入隊列,而每個消費者則依次從隊列中取出資料,看下面的例子:

import threading

import time

import Queue

 

class Producer(threading.Thread):

    def__init__(self,threadname):

       threading.Thread.__init__(self,name=threadname)

    defrun(self):

       global queue

       queue.put(self.getName())

       print self.getName(),'put',self.getName(),'to queue'

 

class Consumer(threading.Thread):

    def__init__(self,threadname):

       threading.Thread.__init__(self,name=threadname)

    defrun(self):

       global queue

       print self.getName(),'get',self.getName(),'from queue'

 

queue=Queue.Queue()

plist=[]

clist=[]

for i in range(10):

   p=Producer('Producer'+str(i))

   plist.append(p)

for i in range(10):

   c=Consumer('Consumer'+str(i))

   clist.append(c)

 

for i in plist:

   i.start()

   i.join()

for i in clist:

   i.start()

   i.join()

   

看結果:

>>>

Producer0 put Producer0 to queue

Producer1 put Producer1 to queue

Producer2 put Producer2 to queue

Producer3 put Producer3 to queue

Producer4 put Producer4 to queue

Producer5 put Producer5 to queue

Producer6 put Producer6 to queue

Producer7 put Producer7 to queue

Producer8 put Producer8 to queue

Producer9 put Producer9 to queue

Consumer0 get Consumer0 from queue

Consumer1 get Consumer1 from queue

Consumer2 get Consumer2 from queue

Consumer3 get Consumer3 from queue

Consumer4 get Consumer4 from queue

Consumer5 get Consumer5 from queue

Consumer6 get Consumer6 from queue

Consumer7 get Consumer7 from queue

Consumer8 get Consumer8 from queue

Consumer9 get Consumer9 from queue

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.