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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

责任编辑:庞桂玉 来源: Hollis
相关推荐

2021-06-03 14:00:35

PolarDB

2021-06-02 16:30:33

PolarDB原子性数据库

2019-02-27 09:28:15

Redis服务器事务

2021-09-08 08:06:57

Redis原子性数据类型

2021-07-03 17:44:34

并发高并发原子性

2024-02-27 17:46:25

并发程序CPU

2013-08-09 09:27:31

2011-08-22 14:19:23

linuxUNIXwrite

2012-05-23 12:49:58

Java自增操作原子性

2021-01-12 07:39:48

线程线程安全

2021-05-16 17:14:30

线程安全性

2021-09-22 12:56:19

编程技能Golang

2021-05-06 19:20:05

Java内存模型

2022-08-17 07:53:10

Volatile关键字原子性

2024-02-26 08:33:51

并发编程活跃性安全性

2023-05-17 08:52:56

Java原子性可见性

2015-08-31 14:37:12

物联网企业

2023-11-07 08:04:19

Go并发程序原子操作

2023-12-14 07:36:16

Java并发原子类

2014-01-09 09:45:41

原子飞原子
点赞
收藏

51CTO技术栈公众号