侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

Python  /  管理员 发布于 7年前   170

锁

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

您可能感兴趣的文章:

  • Python中使用多进程来实现并行处理的方法小结
  • 详解python多线程、锁、event事件机制的简单使用
  • 对Python多线程读写文件加锁的实例详解
  • python使用多进程的实例详解
  • Python并发:多线程与多进程的详解
  • 对Python的多进程锁的使用方法详解


  • 上一条:
    在Python中通过threading模块定义和调用线程的方法
    下一条:
    使用Python编写一个最基础的代码解释器的要点解析
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go语言中实现字符串可逆性压缩及解压缩功能(0个评论)
    • 使用go + gin + jwt + qrcode实现网站生成登录二维码在app中扫码登录功能(0个评论)
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客