#lock #write #optimistic #lock-free #synchronization #data #performance

nightly optimistic_lock_coupling

遵循论文 '乐观锁耦合:一种可扩展且高效的通用同步方法' 的一般锁

3 个不稳定版本

0.2.5 2021年4月14日
0.2.0 2021年4月14日
0.1.0 2021年4月12日

1338数据结构

每月40次下载

Unlicense

1MB
390

乐观锁耦合

CI docs.rs

来自论文 "乐观锁耦合:一种可扩展且高效的通用同步方法"

在实际项目中,当存在许多写冲突时,有一些无锁数据结构,特别是数据库相关的,如 BwTreeSplit-Ordered List(也称为无锁哈希表)。性能损失非常严重,有时甚至不如无脑 Mutex。然而,无脑 Mutex 在正常情况下性能通常很差,那么是否存在一种折中的形式可以解决这个问题?

这就是折中的形式。因此,它可以用作通用锁,并且性能令人满意。

但是,我有一个设计良好且针对使用场景进行了优化的无锁数据结构。它不能成为你的实现吗?

当然,这更好,但你没有114514 PHD学生来优化你的数据结构,也没有1919810位强大的调试大师来处理内存顺序等问题,这会变得棘手。

这时,我的项目已经上线,投资者已经给了我钱。

那么这种数据结构的缺点是什么?

当然有~

这种数据结构的缺点主要在于使用了61位版本,当这个版本满时,我们就可以躺平了。当然,如果你的数据结构疯狂地改变到这个二进制,你应该在写代码时遇到问题。

基准测试

源代码位于 \benches 目录下。你可以在自己的机器上运行它~

在 my MacOS 2.3 GHz Intel Core i5 上的基准测试结果

  • 重读
  • 重写
  • 只读
  • 只写

缺点

乐观锁的缺点很明显。当存在严重冲突时,它会被 Mutex 和其他锁机制撞得粉碎。但当 读 > 写 时,乐观锁表现得更好。

锁的使用

当有3个读取核心和2个写入核心时

移除阻塞日志的中间部分

操作 Delta 时间 线程ID 状态
读取 142869 线程ID(6) OptimisticLockCouplingReadGuard { version: 0, data: 1 }
ErrRead 216320 线程ID(6) 同步失败
ErrRead 222578 线程ID(6) 阻塞
ErrRead 241218 线程ID(6) 阻塞
写入 145456 线程ID(2) OptimisticLockCouplingWriteGuard { version: 0, data: 1 }
写入 291942 线程ID(2) OptimisticLockCouplingWriteGuard { version: 1, data: 2 }
写入 312349 线程ID(2) 乐观锁耦合写保护 { 版本: 2, 数据: 3 }
写错误 147945 线程ID(3) 阻塞
写错误 530522 线程ID(3) 阻塞
写入 319592 线程ID(2) 乐观锁耦合写保护 { 版本: 3, 数据: 4 }
写入 548172 线程ID(2) 乐观锁耦合写保护 { 版本: 4, 数据: 5 }
写入 605291 线程ID(2) 乐观锁耦合写保护 { 版本: 5, 数据: 6 }
写入 613679 线程ID(2) 乐观锁耦合写保护 { 版本: 6, 数据: 7 }
写入 618416 线程ID(2) 乐观锁耦合写保护 { 版本: 7, 数据: 8 }
写入 623453 线程ID(2) 乐观锁耦合写保护 { 版本: 8, 数据: 9 }
写入 627723 线程ID(2) 乐观锁耦合写保护 { 版本: 9, 数据: 10 }
写错误 536923 线程ID(3) 阻塞
写入 696435 线程ID(3) 乐观锁耦合写保护 { 版本: 10, 数据: 11 }
写入 704458 线程ID(3) 乐观锁耦合写保护 { 版本: 11, 数据: 12 }
写入 712664 线程ID(3) 乐观锁耦合写保护 { 版本: 12, 数据: 13 }
写入 718093 线程ID(3) 乐观锁耦合写保护 { 版本: 13, 数据: 14 }
写入 749839 线程ID(3) 乐观锁耦合写保护 { 版本: 14, 数据: 15 }
写入 755558 线程ID(3) 乐观锁耦合写保护 { 版本: 15, 数据: 16 }
ErrRead 149826 线程ID(5) 阻塞
ErrRead 805119 线程ID(5) 阻塞
ErrRead 810206 线程ID(5) 阻塞
写入 775039 线程ID(3) 乐观锁耦合写保护 { 版本: 16, 数据: 17 }
写入 871475 线程ID(3) 乐观锁耦合写保护 { 版本: 17, 数据: 18 }
写入 891289 线程ID(3) 乐观锁耦合写保护 { 版本: 18, 数据: 19 }
写入 896488 线程ID(3) 乐观锁耦合写保护 { 版本: 19, 数据: 20 }
ErrRead 273387 线程ID(6) 阻塞
读取 925559 线程ID(6) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 971184 线程ID(6) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 994963 线程ID(6) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 998833 线程ID(6) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1002179 线程ID(6) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1005515 线程ID(6) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1008870 线程ID(6) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
ErrRead 831229 线程ID(5) 阻塞
读取 1055143 线程ID(5) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1076076 线程ID(5) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1080036 线程ID(5) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1083564 线程ID(5) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1086850 线程ID(5) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1090126 线程ID(5) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1093422 线程ID(5) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1110135 线程ID(5) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1115111 线程ID(5) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1118556 线程ID(5) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1038825 线程ID(6) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1142881 线程ID(6) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1146449 线程ID(6) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
ErrRead 148865 线程ID(4) 阻塞
读取 1197872 线程ID(4) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1217034 线程ID(4) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1220737 线程ID(4) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1224141 线程ID(4) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1227430 线程ID(4) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1230666 线程ID(4) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1233888 线程ID(4) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1237159 线程ID(4) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1240422 线程ID(4) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }
读取 1243714 线程ID(4) 乐观锁耦合读保护 { 版本: 20, 数据: 20 }

无运行时依赖