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

Posted Hollis Chuang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程的原子性 != 事务ACID的原子性相关的知识,希望对你有一定的参考价值。

△Hollis, 一个对Coding有着独特追求的人△

这是Hollis的第 412 篇原创分享

作者 l Hollis

来源 l Hollis(ID:hollischuang)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

如果你喜欢本文,

请长按二维码,关注 Hollis.

转发至朋友圈,是对我最大的支持。

点个 在看 

喜欢是一种感觉

在看是一种支持

↘↘↘

以上是关于并发编程的原子性 != 事务ACID的原子性的主要内容,如果未能解决你的问题,请参考以下文章

事务及分布式事务

事务事务的四大特性(ACID)三大并发问题四种锁事务的隔离级别

数据库管理(事务ACID并发封锁可串行化隔离)(转)

事务 ACID

事务的四个特性-ACID

ACID