# -*- coding: utf-8 -*-
import time
from threading import Lock, RLock
from datetime import datetime
from threading import Thread
import threading class Test:
def __init__(self):
self.obj_lock = Lock()
self.obj_rlock = RLock()
self.a = 1
self.b = 2
self.r = 'r' def t(self):
print('123') def a(self):
with self.obj_lock:
print("a")
self.b() def b(self):
with self.obj_lock:
print("b") def ar(self):
with self.obj_rlock:
print("ar")
self.r = 'ar'
self.br() def br(self):
with self.obj_rlock:
print("br")
self.r = 'br' t = Test()
print(t.a)
t.t()
t.ar()
# t.br()
print('t.r', t.r)

  

https://github.com/python/cpython/blob/master/Doc/library/contextlib.rst

https://github.com/python/cpython/blob/master/Doc/library/contextlib.rst#reentrant-context-managers

Reentrant context managers

More sophisticated context managers may be "reentrant". These context managers can not only be used in multiple :keyword:`with` statements, but may also be used inside a :keyword:`!with` statement that is already using the same context manager.

:class:`threading.RLock` is an example of a reentrant context manager, as are :func:`suppress` and :func:`redirect_stdout`. Here's a very simple example of reentrant use:

>>> from contextlib import redirect_stdout
>>> from io import StringIO
>>> stream = StringIO()
>>> write_to_stream = redirect_stdout(stream)
>>> with write_to_stream:
... print("This is written to the stream rather than stdout")
... with write_to_stream:
... print("This is also written to the stream")
...
>>> print("This is written directly to stdout")
This is written directly to stdout
>>> print(stream.getvalue())
This is written to the stream rather than stdout
This is also written to the stream

Real world examples of reentrancy are more likely to involve multiple functions calling each other and hence be far more complicated than this example.

Note also that being reentrant is not the same thing as being thread safe. :func:`redirect_stdout`, for example, is definitely not thread safe, as it makes a global modification to the system state by binding :data:`sys.stdout` to a different stream.

https://docs.python.org/zh-cn/3/library/threading.html#rlock-objects

重入锁是一个可以被同一个线程多次获取的同步基元组件。在内部,它在基元锁的锁定/非锁定状态上附加了 "所属线程" 和 "递归等级" 的概念。在锁定状态下,某些线程拥有锁 ; 在非锁定状态下, 没有线程拥有它。

acquire(blocking=True, timeout=-1)

可以阻塞或非阻塞地获得锁。

当无参数调用时: 如果这个线程已经拥有锁,递归级别增加一,并立即返回。否则,如果其他线程拥有该锁,则阻塞至该锁解锁。一旦锁被解锁(不属于任何线程),则抢夺所有权,设置递归等级为一,并返回。如果多个线程被阻塞,等待锁被解锁,一次只有一个线程能抢到锁的所有权。在这种情况下,没有返回值。

当调用时参数 blocking 设置为 True ,和没带参数调用一样做同样的事,然后返回 True

blocking 参数设置为 false 的情况下调用,不进行阻塞。如果一个无参数的调用已经阻塞,立即返回false;否则,执行和无参数调用一样的操作,并返回true。

当浮点数 timeout 参数被设置为正值调用时,只要无法获得锁,将最多阻塞 timeout 设定的秒数。 如果锁被获取返回 true,如果超时返回false。

在 3.2 版更改: 新的 timeout 形参。

release()

释放锁,自减递归等级。如果减到零,则将锁重置为非锁定状态(不被任何线程拥有),并且,如果其他线程正被阻塞着等待锁被解锁,则仅允许其中一个线程继续。如果自减后,递归等级仍然不是零,则锁保持锁定,仍由调用线程拥有。

只有当前线程拥有锁才能调用这个方法。如果锁被释放后调用这个方法,会引起 RuntimeError 异常。

没有返回值。

原始锁是一个在锁定时不属于特定线程的同步基元组件。在Python中,它是能用的最低级的同步基元组件,由 _thread 扩展模块直接实现。

该模块的设计基于 Java的线程模型。 但是,在Java里面,锁和条件变量是每个对象的基础特性,而在Python里面,这些被独立成了单独的对象。 Python 的 Thread 类只是 Java 的 Thread 类的一个子集;目前还没有优先级,没有线程组,线程还不能被销毁、停止、暂停、恢复或中断。 Java 的 Thread 类的静态方法在实现时会映射为模块级函数。

下列描述的方法都是自动执行的。

https://docs.python.org/zh-cn/3/library/threading.html#thread-local-data

https://tech.meituan.com/2018/11/15/java-lock.html

cpython/blob/master/Modules/_threadmodule.c

拥有的条件
static PyObject *
rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
{
unsigned long tid = PyThread_get_thread_ident(); if (self->rlock_count > 0 && self->rlock_owner == tid) {
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
} 创建
static PyObject *
rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
rlockobject *self; self = (rlockobject *) type->tp_alloc(type, 0);
if (self != NULL) {
self->in_weakreflist = NULL;
self->rlock_owner = 0;
self->rlock_count = 0; self->rlock_lock = PyThread_allocate_lock();
if (self->rlock_lock == NULL) {
Py_DECREF(self);
PyErr_SetString(ThreadError, "can't allocate lock");
return NULL;
}
} return (PyObject *) self;
} static PyObject *
lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
{
_PyTime_t timeout;
PyLockStatus r; if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
return NULL; r = acquire_timed(self->lock_lock, timeout);
if (r == PY_LOCK_INTR) {
return NULL;
} if (r == PY_LOCK_ACQUIRED)
self->locked = 1;
return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
}

  

如果多线程的场景下,没有在一个线程内的 锁的获取与释放的要求,那么 Rlock的作用 就是否和Lock一样?1

单线程的情况下,lock有的功能点,Rlock也有,反之不成立;

多线程的情况下, 如果有在同一线程内的锁的释放或获取的需求,则用Rlock; 否则,用Lock,因为Rlock的运行逻辑多于Lock,会有更多的资源消耗 性能开销。

https://github.com/python/cpython/blob/master/Doc/library/contextlib.rst 被同一个线程多次获取的同步基元组件的更多相关文章

  1. https://github.com/chenghuige/tensorflow-exp/blob/master/examples/sparse-tensor-classification/

        https://github.com/chenghuige/tensorflow-exp/blob/master/examples/sparse-tensor-classification/ ...

  2. 结对项目https://github.com/bxoing1994/test/blob/master/源代码

    所选项目名称:文本替换      结对人:曲承玉 github地址 :https://github.com/bxoing1994/test/blob/master/源代码 结对人github地址:ht ...

  3. https://github.com/golang/crypto/blob/master/bcrypt/bcrypt.go

    https://github.com/golang/crypto/blob/master/bcrypt/bcrypt.go

  4. https://github.com/PyMySQL/PyMySQL/blob/master/pymysql/connections.py

    # Python implementation of the MySQL client-server protocol # http://dev.mysql.com/doc/internals/en/ ...

  5. https://github.com/tensorflow/models/blob/master/research/slim/datasets/preprocess_imagenet_validation_data.py 改编版

    #!/usr/bin/env python # Copyright 2016 Google Inc. All Rights Reserved. # # Licensed under the Apach ...

  6. GC 的认识(转) https://github.com/qcrao/Go-Questions/blob/master/GC/GC.md#1-什么是-gc有什么作用

    1. 什么是 GC,有什么作用? GC,全称 Garbage Collection,即垃圾回收,是一种自动内存管理的机制. 当程序向操作系统申请的内存不再需要时,垃圾回收主动将其回收并供其他代码进行内 ...

  7. https://github.com/CocoaPods/CocoaPods/search?q=No+such+file+or+directory报错解决方式

    ――― MARKDOWN TEMPLATE ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― ### Command ``` /U ...

  8. 编译python(cpython)的源码及其用途

    获取python的源码 3.x及最新版本的源码:https://github.com/python/cpython python2.7分支的源码:https://github.com/python/c ...

  9. git push ! [rejected] master -> master (non-fast-forward) error: failed to push some refs to 'https://github.com/Operater9/guest' hint: Updates were rejected because the tip of your current bra

    推送本地代码到github报错 git push报错 ! [rejected] master -> master (non-fast-forward) error: failed to push ...

随机推荐

  1. 基于335X平台Linux交换芯片驱动开发

    基于335X平台Linux交换芯片驱动开发   一.软硬件平台资料 1.开发板:创龙AM3359核心板,网口采用RMII形式. 2.Kernel版本:4.4.12,采用FDT 3.交换芯片MARVEL ...

  2. Django图书管理系统(前端对数据库的增删改查)

    图书管理系统 出版社的管理 源码位置:https://gitee.com/machangwei-8/learning_materials/tree/master/%E9%A1%B9%E7%9B%AE/ ...

  3. WEB监控手段

    WEB监控手段: 1.端口       本地: ss . netstat .lsof         ss -ntlp|grep 80|wc -l    (大于等于1)          netsta ...

  4. vue-(过滤器,钩子函数,路由)

    1.局部过滤器 在当前组件内部使用过滤器,修饰一些数据 //声明 filters:{ '过滤器的名字':function(val,a,b){ //a 就是alax ,val就是当前的数据 } } // ...

  5. 微信小程序之循环<block></block>

    (1)<block></block>标签 block常用于结合循环 <block wx:for="{{array}}" wx:key="{{ ...

  6. python 程序练习题

    1.实现isOdd(),参数为整数,如果整数为奇数,返回True,否则返回Flase 代码如下: def isOdd(a): if a%2==0: return False else: return ...

  7. Dubbo源码分析(6):Code2

    背景 定义解码和编码方法. Code2是Code的升级版本. 类图 问题 DubboCodec的父类已经实现了Code2接口并且DubboCodec没有实现Code2接口,为什么要implement ...

  8. thrift 安装

    1.下载 去官网 https://thrift.apache.org/download 下载两个文件,下载地址 http://archive.apache.org/dist/thrift/0.9.3/ ...

  9. Emmet的HTML语法(敲代码的快捷方式)

    Emmet的HTML语法(敲代码的快捷方式)   版权声明:本文为网上转载.   所有操作按下“tab”键即可瞬间完成 元素 1.在编辑器中输入元素名称,即可自动补全生成 HTML 标签,即使不是标准 ...

  10. CentOS 7.5静默安装oracle 11g

    1.安装前环境准备 1.1.配置本地yum源 #因公司内网环境,没有互联网,所以需要配置本地yum源,安装所需依赖包等. #挂载ios镜像centos7.5-1804 [root@oracle ~]# ...