首先了解这两者是什么。

以下说明参考自python官网

Lock:Lock被称为①原始锁,原始锁是一个②在锁定时不属于特定线程的同步基元组件,它是能用的最低级的同步基元组件。原始锁处于 "锁定" 或者 "非锁定" 两种状态之一。它被创建时为非锁定状态。它有两个基本方法, acquire() 和 release() 。当状态为非锁定时, acquire() 将状态改为锁定并立即返回。当状态是锁定时, acquire() 将阻塞至其他线程调用 release() 将其改为非锁定状态,然后 acquire() 调用重置其为锁定状态并返回。 release() 只在锁定状态下调用; 它将状态改为非锁定并立即返回。如果尝试释放一个非锁定的锁,则会引发 RuntimeError  异常。锁支持 上下文管理协议,即支持with语句,下文例子中会用到。

RLock:RLock被称为重入锁,若要锁定锁,线程调用其 acquire() 方法;一旦线程拥有了锁,方法将返回。若要解锁,线程调用 release() 方法。 ③acquire()/release() 对可以嵌套,重入锁必须由获取它的线程释放。一旦线程获得了重入锁,同一个线程再次获取它将不阻塞。只有最终 release() (最外面一对的 release() ) 将锁解开,才能让其他线程继续处理 acquire() 阻塞。;线程必须在每次获取它时释放一次。

两者使用的方法大部分还是相同的,下面根据以上红色强调部分描述一下二者的区别

①是名称的区别,一个叫原始锁,一个叫重入锁,这没啥好说的

②Lock在锁定时不属于特定线程,也就是说,Lock可以在一个线程中上锁,在另一个线程中解锁。而对于RLock来说,只有当前线程才能释放本线程上的锁,即解铃还须系铃人:

import threading
import time lock = threading.Lock()
lock.acquire() def func():
lock.release()
print("lock is released") t = threading.Thread(target=func)
t.start() 输出结果为:lock is released

上面代码中,在主线程中创建锁,并上锁,但是是在t线程中释放锁,结果正常输出,说明一个线程上的锁,可以由另外线程解锁。如果把上面的锁改为RLock则报错

③也是这两者最大的区别了,RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。也就是说,下面的情况对于RLock是允许的:

import threading

rlock = threading.RLock()

def func():
if rlock.acquire(): # 第一把锁
print("first lock")
if rlock.acquire(): # 第一把锁没解开的情况下接着上第二把锁
print("second lock")
rlock.release() # 解开第二把锁
rlock.release() # 解开第一把锁 t = threading.Thread(target=func)
t.start() 输出结果:

first lock
   second lock

注意上面强调的同一线程中,因为对于RLock来说只有当前线程才能释放本线程上的锁,并不能在t1线程中已经执行rlock.acquire,且未释放锁的情况下,在另一个t2线程中还能执行rlock.acquire(这种情况会导致t2阻塞)

那么,既然一个线程可以通过Lock来获得一把锁,干嘛还要使用RLock去锁上加锁?考虑一下这种情况:

import threading
import time lock1 = threading.RLock() def inner():
with lock1:
print("inner1 function:%s" % threading.current_thread()) def outer():
print("outer function:%s" % threading.current_thread())
with lock1:
inner() if __name__ == "__main__":
t1 = threading.Thread(target=outer)
t2 = threading.Thread(target=outer)
t1.start()
t2.start()
结果:

  outer function:<Thread(Thread-1, started 12892)>
  inner1 function:<Thread(Thread-1, started 12892)>
  outer function:<Thread(Thread-2, started 7456)>
  inner1 function:<Thread(Thread-2, started 7456)>

首先只看t1线程,当执行到outer函数时,首先打印outer function:<Thread(Thread-1, started 12892)>,然后用lock1给当前线程上了一把锁,然后执行inner函数,在inner里面又需要用lock1来上一把锁,如果此时用Lock的话,由于已经上了一把锁,程序会因为第二次无法获得锁而导致t1阻塞,程序阻塞之后又没法释放锁,所以会导致程序死锁。这种情况下,RLock就派上用场了。t2线程执行过程和t1一样,这里只是多加个线程看起来酷炫一些

python threading模块的Lock和RLock区别的更多相关文章

  1. Python学习笔记- Python threading模块

    Python threading模块 直接调用 # !/usr/bin/env python # -*- coding:utf-8 -*- import threading import time d ...

  2. python threading模块使用 以及python多线程操作的实践(使用Queue队列模块)

    今天花了近乎一天的时间研究python关于多线程的问题,查看了大量源码 自己也实践了一个生产消费者模型,所以把一天的收获总结一下. 由于GIL(Global Interpreter Lock)锁的关系 ...

  3. python threading模块2

    Thread 是threading模块中最重要的类之一,可以使用它来创建线程.有两种方式来创建线程:一种是通过继承Thread类,重写它的run方法:另一种是创建一个threading.Thread对 ...

  4. Python——threading模块(线程)

    一.threading模块的对象 Thread:表示一个执行线程的对象 Lock:锁 Rlock:可重入锁对象 Condition:条件变量对象,使得一个线程等待另一个线程满足特定的“条件” Even ...

  5. python threading模块中对于信号的抓取

    最近的物联网智能网关(树莓派)项目中遇到这样一个问题:要从多个底层串口读取发来的数据,并且做出相应的处理,对于每个串口的数据的读取我能想到的可以采用两种方式: 一种是采用轮询串口的方式,例如每3s向每 ...

  6. python——threading模块

    一.什么是线程 线程是操作系统能够进行运算调度的最小单位.进程被包含在进程中,是进程中实际处理单位.一条线程就是一堆指令集合. 一条线程是指进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条 ...

  7. python threading 模块来实现多线程

    以多线程的方式向标准输出打印日志 #!/usr/bin/python import time import threading class PrintThread(threading.Thread): ...

  8. Python导入模块Import和from+Import区别

    在我们使用python的时候会发现使用Import可以导入模块,from+Import也可以,那么他们之间有什么区别,该用哪一种呢?让我们来看看 1.首先在demo.py中创建一个变量a,定义一个函数 ...

  9. python threading模块中的join()方法和setDeamon()方法的一些理解

    之前用多线程的时候看见了很多文章,比较常用的大概就是join()和setDeamon()了. 先说一下自己对join()的理解吧: def join(self, timeout=None): &quo ...

随机推荐

  1. 金字塔原理(Pyramid Principle)

    什么是金字塔原理?简单来说,金字塔原理就是“中心论点---分论点---支撑论据”这样的一个结构. 图片摘自:http://www.woshipm.com/pmd/306704.html 人类通常习惯于 ...

  2. ImageView.ScaleType

    前言 对ImageView.ScaleType,学习安卓需掌握.以官方链接:http://android.xsoftlab.net/reference/android/widget/ImageView ...

  3. 手把手教你用Python代码实现微信聊天机器人 -- Python wxpy

    关注我,每天都有优质技术文章推送,工作,学习累了的时候放松一下自己. 本篇文章同步微信公众号 欢迎大家关注我的微信公众号:「醉翁猫咪」 来学习了,微信聊天机器人. 环境要求: Windows / Li ...

  4. Hadoop运行原理总结(详细)

    本编随笔是小编个人参照个人的笔记.官方文档以及网上的资料等后对HDFS的概念以及运行原理进行系统性地归纳,说起来真的惭愧呀,自学了很长一段时间也没有对Hadoop知识点进行归纳,有时候在实战中或者与别 ...

  5. how does SELECT TOP works when no order by is specified?

    how does SELECT TOP works when no order by is specified? There is no guarantee which two rows you ge ...

  6. Android相关属性的介绍:android:exported = true

    在Activity中该属性用来标示:当前Activity是否可以被另一个Application的组件启动:true允许被启动:false不允许被启动. android:exported 是Androi ...

  7. SnowFlake分布式ID生成及反解析

    概述 分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种,SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图: 1位,不用.二进制中最高位为 ...

  8. [转]CSS3 使用 calc() 计算高度 vh px

    1.px 像素,我们在网页布局中一般都是用px. 2.百分比 百分比一般宽泛的讲是相对于父元素,自适应网页布局越来越多,百分比也经常用到了. 3.Viewport    viewport:可视窗口,也 ...

  9. pytorch ImageFolder的覆写

    在为数据分类训练分类器的时候,比如猫狗分类时,我们经常会使用pytorch的ImageFolder: CLASS torchvision.datasets.ImageFolder(root, tran ...

  10. sqlserver表被锁了,解锁方法,删除锁的方法

    -- 查询死锁select        request_session_id spid,       OBJECT_NAME(resource_associated_entity_id) table ...