https://github.com/python/cpython/blob/master/Doc/library/contextlib.rst 被同一个线程多次获取的同步基元组件
# -*- 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 被同一个线程多次获取的同步基元组件的更多相关文章
- https://github.com/chenghuige/tensorflow-exp/blob/master/examples/sparse-tensor-classification/
https://github.com/chenghuige/tensorflow-exp/blob/master/examples/sparse-tensor-classification/ ...
- 结对项目https://github.com/bxoing1994/test/blob/master/源代码
所选项目名称:文本替换 结对人:曲承玉 github地址 :https://github.com/bxoing1994/test/blob/master/源代码 结对人github地址:ht ...
- https://github.com/golang/crypto/blob/master/bcrypt/bcrypt.go
https://github.com/golang/crypto/blob/master/bcrypt/bcrypt.go
- 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/ ...
- 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 ...
- GC 的认识(转) https://github.com/qcrao/Go-Questions/blob/master/GC/GC.md#1-什么是-gc有什么作用
1. 什么是 GC,有什么作用? GC,全称 Garbage Collection,即垃圾回收,是一种自动内存管理的机制. 当程序向操作系统申请的内存不再需要时,垃圾回收主动将其回收并供其他代码进行内 ...
- https://github.com/CocoaPods/CocoaPods/search?q=No+such+file+or+directory报错解决方式
――― MARKDOWN TEMPLATE ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― ### Command ``` /U ...
- 编译python(cpython)的源码及其用途
获取python的源码 3.x及最新版本的源码:https://github.com/python/cpython python2.7分支的源码:https://github.com/python/c ...
- 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 ...
随机推荐
- 详解微信公众平台UnionID和OpenID的区别
OpenID: 普通用户的标识,对当前开发者帐号唯一.一个openid对应一个公众号. UnionID :用户统一标识.针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的. 微信的 ...
- MyBatis 多表连接查询
多表连接的两种方式(数据库逻辑模型): 1.一对一关系 2.一对多关系 一.通过 resultMap 和 association 实现一对一关系 在 mapper.xml 文件里面的代码: <r ...
- Flask统计代码行数
流程: 1.获取前端的文件 2.判断文件是否zip文件 3.解压压缩包并保存 4.遍历解压后的文件夹 5.判断文件是否py文件,将绝对路径添加到列表 6.循环列表,排除注释和空号,统计行数 from ...
- 【转】DSP动态内存分配函数的使用
DSP里的动态内存分配,其分配的内存区域在在堆(heap)中.同时DSP里动态分配内存的函数还有calloc以及reclloc.这些动态分配的内存放置在.system段的全局池或堆(heap)中.因此 ...
- css背景雪碧图等
1.背景图 雪碧图技术 要设置背景,是要设置在某个盒子上 <!doctype html> <html lang="en"> <head> < ...
- vs中找到接口和抽象类的具体实现类
如何找到接口和抽象类的具体实现类 1,可以使用:ctrl+k clrl+t打开调用层次结构窗口: 2,移动到实现节点: 3,然后可以转到具体实现: 第二种安装插件 ReSharper 第三种方法: 在 ...
- jmeter性能测试监控
Jmeter监控服务器资源配置如下: 1.进入https://jmeter-plugins.org/downloads/all/下载plugins-manager.jar,放置到jmeter安装目录/ ...
- Redis中如何保证数据库和缓存双写时的数据的一致性?
简单的场景: 直接使用 1. 使用Cache Aside pattern 读取的时候,先读取缓存中是否有数据,缓存中没有数据,再去数据库中进行查询,查询出来以后,然后再存入到缓存中 更新的时候,先删除 ...
- vue 标签页以及标签页赋值
背景: 使用vue增加了标签页,点击不同标签页传给后端的值不一样,用来做区分,如图: vue代码如下: 使用 form.PageA form.PageB ,后端接收到的值 first.second ...
- set/priority_queue的运算符重载
#include<bits/stdc++.h> using namespace std; struct cmp { bool operator ()(int a, int b) //重载小 ...