天道不一定酬所有勤
但是,天道只酬勤

并发编程的原子性 != 事务ACID的原子性

GitHub 24k Star 的Java工程师成神之路,不来了解一下吗!

关于原子性,很多人在多个地方都听说过,大家也都背的很熟悉。

在事务的ACID中,有原子性的概念,在并发编程的原子性、可见性、有序性中也有原子性的概念。

有人认为他们是一样的,甚至很多人在说原子性的时候也都是这么说的:

原子性是指事务是一个不可再分割的工作单元,事务中的操作要么都发生,要么都不发生。

但是,其实,虽然都叫原子性,但是此原子性非彼原子性。

在数据库中的原子性,确实是一个不可拆分的工作单元,要么都执行,要么都不执行。因为事务可以Commit、也可以Rollback。

但是在并发编程中,一个操作是没办法rollback的,并且线程在执行过程中也是有可能失败的,失败了是没办法回滚的,难道就说一个操作没办法保证原子性了么?

所以,在并发编程中,我们把一个或者多个操作在 CPU 执行的过程中不被中断的特性称为原子性。这里的原子性是通过加锁的方式来保证的,其实保证的就是一系列操作,不可以被拆分执行,即执行过程中,需要互斥排他,不能有其他线程进行执行。

举一个例子来说明一下这两个原子性的区别。

Redis中的Lua脚本到底能不能保证原子性?

网上很多文章,有人说能,有人说不能。要我说,都对,也都不对。就是因为因为大家搞混了这两个原子性的区别。

我们都知道,当我们想要在一个事务中执行多个命令的时候,会选择使用Lua脚本。

Redis会将一个要执行的Lua脚本封装成一个单独的事务,而脚本执行器在执行这个事务的过程中,

如果有其他客户端请求的时候,会把它暂存起来,等脚本处理完以后,才会再把被暂存的请求恢复执行。

这样就可以保证整个脚本是作为一个整体执行的,中间不会被其他命令插入,这就是所谓的原子性中的”不可拆分”特性。

但是,如果事务执行过程中命令产生错误,事务是不会回滚的,也不会影响后续命令的执行。

也就是说,Redis保证以原子方式执行Lua脚本,但是不保证脚本中所有操作要么都执行或者都回滚。

那就意味着,Redis中Lua脚本的执行,可以保证并发编程中不可再拆分的这个原子性,但是没有保证数据库ACID中要么都执行要么都回滚的这个原子性。

(全文完)

扫描二维码,关注作者微信公众号
赞(0)
如未加特殊说明,此网站文章均为原创,转载必须注明出处。HollisChuang's Blog » 并发编程的原子性 != 事务ACID的原子性
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

HollisChuang's Blog

联系我关于我