舉例講解Python編程中對線程鎖的使用

來源:互聯網
上載者:User

python的內建資料結構比如列表和字典等是安全執行緒的,但是單一資料型別比如整數和浮點數則不是安全執行緒的,要這些單一資料型別的通過操作,就需要使用鎖。

#!/usr/bin/env python3# coding=utf-8import threadingshared_resource_with_lock = 0shared_resource_with_no_lock = 0COUNT = 100000shared_resource_lock = threading.Lock()####LOCK MANAGEMENT##def increment_with_lock():  global shared_resource_with_lock  for i in range(COUNT):    shared_resource_lock.acquire()    shared_resource_with_lock += 1    shared_resource_lock.release()    def decrement_with_lock():  global shared_resource_with_lock  for i in range(COUNT):    shared_resource_lock.acquire()    shared_resource_with_lock -= 1    shared_resource_lock.release()    ####NO LOCK MANAGEMENT ##  def increment_without_lock():  global shared_resource_with_no_lock  for i in range(COUNT):    shared_resource_with_no_lock += 1  def decrement_without_lock():  global shared_resource_with_no_lock  for i in range(COUNT):    shared_resource_with_no_lock -= 1  ####the Main programif __name__ == "__main__":  t1 = threading.Thread(target = increment_with_lock)  t2 = threading.Thread(target = decrement_with_lock)  t3 = threading.Thread(target = increment_without_lock)  t4 = threading.Thread(target = decrement_without_lock)  t1.start()  t2.start()  t3.start()  t4.start()  t1.join()  t2.join()  t3.join()  t4.join()  print ("the value of shared variable with lock management is %s"\  %shared_resource_with_lock)  print ("the value of shared variable with race condition is %s"\  %shared_resource_with_no_lock)

執行結果:

$ ./threading_lock.py 
the value of shared variable with lock management is 0the value of shared variable with race condition is 0

又如:

import randomimport threadingimport timelogging.basicConfig(level=logging.DEBUG,          format='(%(threadName)-10s) %(message)s',          )          class Counter(object):  def __init__(self, start=0):    self.lock = threading.Lock()    self.value = start  def increment(self):    logging.debug(time.ctime(time.time()))    logging.debug('Waiting for lock')    self.lock.acquire()    try:      pause = random.randint(1,3)      logging.debug(time.ctime(time.time()))      logging.debug('Acquired lock')            self.value = self.value + 1      logging.debug('lock {0} seconds'.format(pause))      time.sleep(pause)    finally:      self.lock.release()def worker(c):  for i in range(2):    pause = random.randint(1,3)    logging.debug(time.ctime(time.time()))    logging.debug('Sleeping %0.02f', pause)    time.sleep(pause)    c.increment()  logging.debug('Done')counter = Counter()for i in range(2):  t = threading.Thread(target=worker, args=(counter,))  t.start()logging.debug('Waiting for worker threads')main_thread = threading.currentThread()for t in threading.enumerate():  if t is not main_thread:    t.join()logging.debug('Counter: %d', counter.value)

執行結果:

$ python threading_lock.py 

(Thread-1 ) Tue Sep 15 15:49:18 2015(Thread-1 ) Sleeping 3.00(Thread-2 ) Tue Sep 15 15:49:18 2015(MainThread) Waiting for worker threads(Thread-2 ) Sleeping 2.00(Thread-2 ) Tue Sep 15 15:49:20 2015(Thread-2 ) Waiting for lock(Thread-2 ) Tue Sep 15 15:49:20 2015(Thread-2 ) Acquired lock(Thread-2 ) lock 2 seconds(Thread-1 ) Tue Sep 15 15:49:21 2015(Thread-1 ) Waiting for lock(Thread-2 ) Tue Sep 15 15:49:22 2015(Thread-1 ) Tue Sep 15 15:49:22 2015(Thread-2 ) Sleeping 2.00(Thread-1 ) Acquired lock(Thread-1 ) lock 1 seconds(Thread-1 ) Tue Sep 15 15:49:23 2015(Thread-1 ) Sleeping 2.00(Thread-2 ) Tue Sep 15 15:49:24 2015(Thread-2 ) Waiting for lock(Thread-2 ) Tue Sep 15 15:49:24 2015(Thread-2 ) Acquired lock(Thread-2 ) lock 1 seconds(Thread-1 ) Tue Sep 15 15:49:25 2015(Thread-1 ) Waiting for lock(Thread-1 ) Tue Sep 15 15:49:25 2015(Thread-1 ) Acquired lock(Thread-1 ) lock 2 seconds(Thread-2 ) Done(Thread-1 ) Done(MainThread) Counter: 4

acquire()中傳入False值,可以檢查是否獲得了鎖。比如:

import loggingimport threadingimport timelogging.basicConfig(level=logging.DEBUG,          format='(%(threadName)-10s) %(message)s',          )          def lock_holder(lock):  logging.debug('Starting')  while True:    lock.acquire()    try:      logging.debug('Holding')      time.sleep(0.5)    finally:      logging.debug('Not holding')      lock.release()    time.sleep(0.5)  return          def worker(lock):  logging.debug('Starting')  num_tries = 0  num_acquires = 0  while num_acquires < 3:    time.sleep(0.5)    logging.debug('Trying to acquire')    have_it = lock.acquire(0)    try:      num_tries += 1      if have_it:        logging.debug('Iteration %d: Acquired',               num_tries)        num_acquires += 1      else:        logging.debug('Iteration %d: Not acquired',               num_tries)    finally:      if have_it:        lock.release()  logging.debug('Done after %d iterations', num_tries)lock = threading.Lock()holder = threading.Thread(target=lock_holder,             args=(lock,),             name='LockHolder')holder.setDaemon(True)holder.start()worker = threading.Thread(target=worker,             args=(lock,),             name='Worker')worker.start()

執行結果:

$ python threading_lock_noblock.py 

(LockHolder) Starting(LockHolder) Holding(Worker  ) Starting(LockHolder) Not holding(Worker  ) Trying to acquire(Worker  ) Iteration 1: Acquired(LockHolder) Holding(Worker  ) Trying to acquire(Worker  ) Iteration 2: Not acquired(LockHolder) Not holding(Worker  ) Trying to acquire(Worker  ) Iteration 3: Acquired(LockHolder) Holding(Worker  ) Trying to acquire(Worker  ) Iteration 4: Not acquired(LockHolder) Not holding(Worker  ) Trying to acquire(Worker  ) Iteration 5: Acquired(Worker  ) Done after 5 iterations

安全執行緒鎖

threading.RLock()

返回可重新進入鎖對象。重入鎖必須由獲得它的線程釋放。一旦線程獲得了重入鎖,同一線程可不阻塞地再次獲得,擷取之後必須釋放。

通常一個線程只能擷取一次鎖:

import threadinglock = threading.Lock()print 'First try :', lock.acquire()print 'Second try:', lock.acquire(0)

執行結果:

$ python threading_lock_reacquire.py

First try : TrueSecond try: False

使用RLock可以擷取多次鎖:

import threadinglock = threading.RLock()print 'First try :', lock.acquire()print 'Second try:', lock.acquire(0)

執行結果:

python threading_rlock.py 

First try : TrueSecond try: 1

再來看一個例子:

#!/usr/bin/env python3# coding=utf-8import threadingimport timeclass Box(object):  lock = threading.RLock()  def __init__(self):    self.total_items = 0  def execute(self,n):    Box.lock.acquire()    self.total_items += n    Box.lock.release()  def add(self):    Box.lock.acquire()    self.execute(1)    Box.lock.release()  def remove(self):    Box.lock.acquire()    self.execute(-1)    Box.lock.release()    ## These two functions run n in separate## threads and call the Box's methods    def adder(box,items):  while items > 0:    print ("adding 1 item in the box\n")    box.add()    time.sleep(5)    items -= 1    def remover(box,items):  while items > 0:    print ("removing 1 item in the box")    box.remove()    time.sleep(5)    items -= 1    ## the main program build some## threads and make sure it worksif __name__ == "__main__":  items = 5  print ("putting %s items in the box " % items)  box = Box()  t1 = threading.Thread(target=adder,args=(box,items))  t2 = threading.Thread(target=remover,args=(box,items))  t1.start()  t2.start()  t1.join()  t2.join()  print ("%s items still remain in the box " % box.total_items)

執行結果:

$ python3 threading_rlock2.py 

putting 5 items in the box adding 1 item in the boxremoving 1 item in the boxadding 1 item in the boxremoving 1 item in the boxadding 1 item in the boxremoving 1 item in the boxremoving 1 item in the boxadding 1 item in the boxremoving 1 item in the boxadding 1 item in the box0 items still remain in the box
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.