cython中实现的快速、可重入乐观锁

fastrlock的Python项目详细描述


快速锁定

这是cpython快速、可重入、乐观锁的c级实现。 这是一个替代品 threading.RLock。 fastrlock在Cython中实现,还提供了一个c-api 从cython代码通过from fastrlock cimport rlock直接使用。

在正常情况下,它比Python2.7中的threading.rlock快10倍。 因为它避免了所有的锁定,除非两个或多个线程尝试在 同时。在拥挤的情况下,它仍然比rlock快10%左右,因为 在cython中实现。

这基本上相当于python 3.2中修改过的rlock实现, 但由于在cython中实现,速度更快。但是,在python 3.4和 稍后,stdlib中的threading.RLock实现往往同样快 或者甚至比这个包提供的锁更快,当通过 python api。FastRLock在这些系统上调用时仍然更快 通过其他cython模块的cython api。

最初在这里作为代码配方发布: https://code.activestate.com/recipes/577336-fast-re-entrant-optimistic-lock-implemented-in-cyt/

fastrlock已经在Lupa中使用和测试了好几年。

它是如何工作的?

fastrlock实现可针对非拥塞情况进行优化。它的工作原理是 利用gil的可用性。因为它知道当 调用了acquire()/release()方法,它可以安全地检查锁 由其他线程持有,只要总是 获取它的同一线程。这比实际获得 底层锁。

当第二个线程也想获取锁时,它首先检查锁 数一数,发现锁已经被拥有了。如果底层锁也是 已经被另一个线程持有,然后它释放gil并请求获得 锁,就像rlock一样。但是,如果未持有基础锁,则 通过告知 现在的主人可以在完成后释放它。然后,它又回到了正常状态 要求锁的非所有者行为,并最终在锁 被释放。这确保只有在至少 两条线需要它。

所有这些操作基本上都是原子的,因为任何修改 锁定状态始终保持gil。注意,实现不能调用任何 处理锁时的python代码,因为调用python可能会导致上下文 把gil交给另一个线程,从而打破原子性。 因此,代码错误地使用了cython的“nogil”注释,以确保没有python 代码意外插入。

有多快?

以下是Python2.7在以下情况下的一些计时:

  1. 五个获取释放周期(“锁定解锁”)
  2. 五个acquire调用,然后是五个release调用(嵌套锁,“可重入锁”unlock“)
  3. 一个混合和部分嵌套的获取和释放调用序列(“mixed_lock_unlock”)
  4. 五个不阻塞的获取释放周期(“锁定/解锁/非阻塞”)

所有四个都是针对单线程和多线程情况进行基准测试的 有10根线。我还用20个线程测试了它,结果发现 两个版本的时间大约是两倍。还要注意,拥挤的情况是 两个锁的速度都要慢得多,所以我在这里只循环了1000次 单螺纹壳体的计时而不是100000倍。

Testing threading.RLock

sequential (x100000):
lock_unlock              : 1.408 sec
reentrant_lock_unlock    : 1.089 sec
mixed_lock_unlock        : 1.212 sec
lock_unlock_nonblocking  : 1.415 sec

threaded 10T (x1000):
lock_unlock              : 1.188 sec
reentrant_lock_unlock    : 1.039 sec
mixed_lock_unlock        : 1.068 sec
lock_unlock_nonblocking  : 1.199 sec

Testing FastRLock

sequential (x100000):
lock_unlock              : 0.122 sec
reentrant_lock_unlock    : 0.124 sec
mixed_lock_unlock        : 0.137 sec
lock_unlock_nonblocking  : 0.156 sec

threaded 10T (x1000):
lock_unlock              : 0.911 sec
reentrant_lock_unlock    : 0.938 sec
mixed_lock_unlock        : 0.953 sec
lock_unlock_nonblocking  : 0.916 sec

与Python3.2及更高版本相比如何?

下面是使用py3.2运行的相同基准:

Testing threading.RLock

sequential (x100000):
lock_unlock              : 0.134 sec
reentrant_lock_unlock    : 0.120 sec
mixed_lock_unlock        : 0.151 sec
lock_unlock_nonblocking  : 0.177 sec

threaded 10T (x1000):
lock_unlock              : 0.885 sec
reentrant_lock_unlock    : 0.972 sec
mixed_lock_unlock        : 0.883 sec
lock_unlock_nonblocking  : 0.911 sec

Testing FastRLock

sequential (x100000):
lock_unlock              : 0.093 sec
reentrant_lock_unlock    : 0.093 sec
mixed_lock_unlock        : 0.104 sec
lock_unlock_nonblocking  : 0.112 sec

threaded 10T (x1000):
lock_unlock              : 0.943 sec
reentrant_lock_unlock    : 0.871 sec
mixed_lock_unlock        : 0.920 sec
lock_unlock_nonblocking  : 0.908 sec

因此,在单线程的情况下,py3.2中的c实现仅为 大约比cython实现慢20-50%,然而 在拥挤的情况下,速度差不多。

快速锁定更改日志

0.4(2018-08-24)

  • 用cython 0.28.5重建。
  • 通过配置文件引导的优化,Linux控制盘速度更快。
  • 将缺少的文件添加到sdist。 (由Mark Harfouche修补,Github第5期)

0.3(2017-08-10)

  • 改进c-api的cimport支持 (由naotoshi seo提供补丁,github问题3)
  • 提供fastrlock.__version__

0.2(2017-08-09)

  • 将缺少的自述文件添加到sdist

0.1(2017-06-04)

  • 初始版本

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
在Java中使用BufferedReader类读取文本文件的子字符串   java如何在JSP页面上包含来自另一台服务器的动态JSP   使用单表策略的java持久化Hibernate继承映射   java报告状态失败达600秒。谋杀!报告hadoop的进展   java将字符串解析为形状   使用JTable的java ClassCastException?   java在Spring引导中关闭数据库   java Android Studio调试错误(Ubuntu)   java如何区分apache beam中KV实例中的两个键?   java将RealmObjectChangeListener添加到异步下载的RealmObject   java匹配模式之前的所有内容,包括新行和/或回车   java使用JAXB在XML中动态更改元素序列   java如何在MACOS中找到动态库(.dylib文件)的版本   Android中的java Nanohttpd服务器   java libGDX:3d动画不工作