性能文章>并发编程的原子性 != 事务ACID的原子性>

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

1年前
255933

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

 

关于作者:Hollis,一个对Coding有着独特追求的人,现任阿里巴巴技术专家,个人技术博主,技术文章全网阅读量数千万,《程序员的三门课》联合作者。

 

点赞收藏
Hollis

Hollis,一个对Coding有着独特追求的人。现任阿里巴巴技术专家,《程序员的三门课》联合作者。

请先登录,查看3条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

JDBC PreparedStatement 字段值为null导致TBase带宽飙升的案例分析

JDBC PreparedStatement 字段值为null导致TBase带宽飙升的案例分析

随机一门技术分享之Netty

随机一门技术分享之Netty

MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

3
3