43 | 软件事务内存:借鉴数据库的并发经验
王宝令
该思维导图由 AI 生成,仅供参考
很多同学反馈说,工作了挺长时间但是没有机会接触并发编程,实际上我们天天都在写并发程序,只不过并发相关的问题都被类似 Tomcat 这样的 Web 服务器以及 MySQL 这样的数据库解决了。尤其是数据库,在解决并发问题方面,可谓成绩斐然,它的事务机制非常简单易用,能甩 Java 里面的锁、原子类十条街。技术无边界,很显然要借鉴一下。
其实很多编程语言都有从数据库的事务管理中获得灵感,并且总结出了一个新的并发解决方案:软件事务内存(Software Transactional Memory,简称 STM)。传统的数据库事务,支持 4 个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),也就是大家常说的 ACID,STM 由于不涉及到持久化,所以只支持 ACI。
STM 的使用很简单,下面我们以经典的转账操作为例,看看用 STM 该如何实现。
用 STM 实现转账
我们曾经在《05 | 一不小心就死锁了,怎么办?》这篇文章中,讲到了并发转账的例子,示例代码如下。简单地使用 synchronized 将 transfer() 方法变成同步方法并不能解决并发问题,因为还存在死锁问题。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
软件事务内存(STM)是一种借鉴数据库并发经验的新型并发解决方案。文章首先指出,尽管许多开发者可能没有直接接触并发编程,但实际上在日常编程中,类似数据库和Web服务器已经解决了许多并发相关问题。STM受数据库事务管理的启发,通过实现原子性、一致性和隔离性来解决并发问题。相比传统的数据库事务,STM不涉及持久化,因此只支持ACI(原子性、一致性、隔离性)。 文章以转账操作为例,对比了使用数据库事务和STM的实现方式。在STM中,通过atomic()方法实现了并发问题的解决,相较于传统方法更为简单。STM的实现基于MVCC(多版本并发控制),类似于数据库事务的乐观锁。文章还介绍了如何自己实现STM,包括对数据的版本管理和事务的提交过程。 总的来说,STM借鉴了数据库的经验,但并非万能解决方案。目前主要应用于函数式编程语言,利用不可变性实现STM相对简单。文章最后提到了对STM实现的优化方法,并鼓励读者分享想法和思考。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 并发编程实战》,新⼈⾸单¥59
《Java 并发编程实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(26)
- 最新
- 精选
- M$画像希望王老师再出新品,一定支持。
作者回复: 感谢捧场😄
2019-06-2422 - 小文同学谢谢老师推荐STM,我所在的游戏项目一直有对象异步入库的需求,为了使用异步入库,放弃了Spring针对数据库的事务。为此不得不编写大量代码去判断某个操作是否可以执行,希望软件事务内存可以为我的需求提供一个新的解决方案。最近几天开始研究相关源码了,希望可以较好的结合现有项目,有可以发布的成果一定在留言区为大家共享。
作者回复: 👍期待你的成果!
2019-09-06920 - helloworld按照老师自己实现的STM程序,根本不存在commit提交失败的时候吧?因为每一次的commit都是新创建一个STMTxn,新创建STMTxn后,inTxnMap和writeMap都是新的。不知道我考虑的对不对??
作者回复: 不是这样的,不同的STMTxn持有的TxnRef是共享的,TxnRef内部有版本号,主要依赖这个版本号来检测冲突
2019-09-2346 - 黄海峰代码里硬是没看到哪里修改了version。。
作者回复: 只创建新的版本,永远不会去修改
2019-06-062 - Geek_039a5c代码还有有点小问题。 STM 这个类的代码 花括号写的不对。
编辑回复: 收到,谢谢反馈,我和老师确认下
2022-02-05 - 石头汤是不是 STM.atomic 的 TxnRunnable 的实现必须是幂等的,否则 while 循环那里会产生脏数据?
作者回复: 如果有冲突,写操作不会执行,所以不会产生脏数据
2020-06-11 - 纷繁的烟火最后段代码的 构造参数里的txn在哪呀 找也找不到
作者回复: atomic方法内传入的,lambda表达式可以找专门的资料看看
2020-01-14 - 有铭老师,关系数据库也是有死锁的,只是他们往往实现了死锁检测机制,死锁到一定时间就会强制解锁
作者回复: 当然有死锁,但是数据库的目标是努力消除他们,有些是数据库的bug,有些是我们没有用好
2019-06-06 - 松小鼠我公司用的就是这个解决并发问题的,才知道是这种技术2019-06-06511
- 小太阳看了三遍,终于看懂了,很妙。原来精华就在这一段:MVCC 可以简单地理解为数据库事务在开启的时候,会给数据库打一个快照,以后所有的读写都是基于这个快照的。当提交事务的时候,如果所有读写过的数据在该事务执行期间没有发生过变化,那么就可以提交;如果发生了变化,说明该事务和有其他事务读写的数据冲突了,这个时候是不可以提交的。Txn负责维护检测快照,TxnRef负责包装数据使之可以接入Txn,作为快照的key。VersionedRef负责包装数据使之有版本。 另外,最后的代码里忘了判断余额是否够用了。😁2020-07-08210
收起评论