首页 > 编程 > Python > 正文

举例讲解Python编程中对线程锁的使用

2019-11-25 16:38:33
字体:
来源:转载
供稿:网友

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
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表