并发编程:Atomic类与悲观锁和乐观锁

开发 前端
CAS都是基于“值”来做比较的。但如果另外一个线程把变量的值从A改为B,再从B改回 到A,那么尽管修改过两次,可是在当前线程做CAS操作的时候,却会因为值没变而认为数据没有被其他 线程修改过,这就是所谓的ABA问题。

一、悲观锁与乐观锁

对于悲观锁,认为数据发生并发冲突的概率很大,读操作之前就上锁。synchronized关键字,后面 要讲的ReentrantLock都是悲观锁的典型。

对于乐观锁,认为数据发生并发冲突的概率比较小,读操作之前不上锁。等到写操作的时候,再判 断数据在此期间是否被其他线程修改了。如果被其他线程修改了,就把数据重新读出来,重复该过程; 如果没有被修改,就写回去。判断数据是否被修改,同时写回新值,这两个操作要合成一个原子操作, 也就是CAS ( Compare And Set )。

AtomicInteger的实现就是典型的乐观锁。

AtomicInteger的实现就用的是“自旋”策略,如果拿不到锁,就会一直重试。

二、ABA问题与解决办法

到目前为止,CAS都是基于“值”来做比较的。但如果另外一个线程把变量的值从A改为B,再从B改回 到A,那么尽管修改过两次,可是在当前线程做CAS操作的时候,却会因为值没变而认为数据没有被其他 线程修改过,这就是所谓的ABA问题。

举例来说: 小张欠小李100块,约定今天还,给打到网银。 小李家的网银余额是0,打过来之后应该是100块。 小张今天还钱这个事小李知道,小李还告诉了自己媳妇。 小张还钱,小李媳妇看到了,就取出来花掉了。 小李恰好在他媳妇取出之后检查账户,一看余额还是0。 然后找小张,要账。

这其中,小李家的账户余额从0到100,再从100到0,小李一开始检查是0,第二次检查还是0,就 认为小张没还钱。 实际上小李媳妇花掉了。 ABA问题。 其实小李可以查看账户的收支记录。

要解决 ABA 问题,不仅要比较“值”,还要比较“版本号”,而这正是 AtomicStampedReference做的事情。

责任编辑:武晓燕 来源: 今日头条
相关推荐

2020-07-06 08:03:32

Java悲观锁乐观锁

2009-09-25 16:43:44

Hibernate悲观Hibernate乐观

2023-02-23 10:32:52

乐观锁

2021-03-30 09:45:11

悲观锁乐观锁Optimistic

2024-01-29 01:08:01

悲观锁递归锁读写锁

2011-08-18 13:44:42

Oracle悲观锁乐观锁

2010-08-18 09:00:38

数据库

2019-04-19 09:48:53

乐观锁悲观锁数据库

2019-11-28 16:00:06

重入锁读写锁乐观锁

2019-05-05 10:15:42

悲观锁乐观锁数据安全

2019-01-04 11:18:35

独享锁共享锁非公平锁

2018-07-31 10:10:06

MySQLInnoDB死锁

2023-08-17 14:10:11

Java开发前端

2020-09-16 07:56:28

多线程读写锁悲观锁

2020-10-22 08:21:37

乐观锁、悲观锁和MVC

2024-01-05 16:43:30

数据库线程

2021-01-15 05:12:14

Java并发乐观锁

2023-10-13 00:00:00

并发乐观锁CAS

2021-12-27 10:13:51

Goatomic数据竞争

2024-01-10 08:01:55

高并发场景悲观锁
点赞
收藏

51CTO技术栈公众号