JAVA并发锁 - 悲观锁VS乐观锁(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sunyanxiong123/article/details/84642289


在讨论锁相关概念和原理之前,我们先来了解一下线程安全的问题,线程安全主要有以下两方面影响:
1.操作中存在临界资源,也称共享资源。
2.系统中存在多线程操作临界资源。

常见的解决方案:
当系统中存在多个线程操作临界资源时,我们需要保证线程之间的共享资源可见,当其中一个线程获取到操作共享资源的权利后,会对该资源进行加锁限制,防止其它线程再对该资源进行修改,当该线程操作完后,会释放资源锁。

悲观锁VS乐观锁

在并发操作中,为了实现线程之间的资源共享,保证数据的一致性,通常需要进行线程间数据同步,在java中同步有很多种方式,其中 synchronized 是最常见的一种实现资源同步的方式,对资源进行加锁。接下来我们首先研究下 悲观锁和乐观锁。简单总结如下图所示:
在这里插入图片描述

1.悲观锁

1.1什么是悲观锁

悲观锁:线程进行并发操作时,总是以最坏的情况进行操作,假设总有其它线程会对资源进行更新,所以,当线程获取到资源时,会对资源进行加锁操作,避免其它线程对资源进行更新,等待当前线程操作完后,会释放锁,此时其它线程可以获取资源,并完成相应的操作。

1.2源码分析

synchronized

synchronized 关键字在java中使用很频繁,使用该关键字可以资源进行加锁,本质上采用抢占式获取锁的机制,是一种典型的悲观锁。synchronized 也是一种互斥锁。关于互斥锁将在后续文章中做出说明。

  • 三种应用方式

实例方法块
静态方法块
代码块

  • 底层原理
  • java虚拟机对synchronized的优化
  • 关注点

Lock

1.3应用场景

悲观锁应用场景:
并发访问中存在频繁更新数据操作。

1.4实现

2乐观锁

2.1什么是乐观锁

乐观锁:线程进行并发操作时,总是以最好的情况进行操作,假设没有其它线程会对资源进行操作,如果当前线程只是进行查询操作,那么获取到当前最新的数据返回给接口即可,【至于这个共享资源在获取过程中会被其它线程更改,获取到的资源可能不是最新的,导致出现这个问题应该归于其它线程更新共享资源的一种机制】。如果当前线程需要对共享资源进行更新操作,那么常常会采用一种校对更换的机制,即 CAS(Compare And Swap)。CAS原理将在下面进行介绍。

2.2源码分析

CAS 原理

cas是一种无锁机制,在不使用锁的情况下实现多线程之间的资源共享,cas中有三个值:需要读写的内存值V,需要进行比较的值A,需要更新的值B(需要写入内存)。

当且仅当V == A时,才会进行更新操作V=B(将V值替换为B),更新操作是一个不断重试的机制,如果不满足V==A,会一直重试,直到满足后作更新操作。

CAS 问题

  • ABA问题
  • 更新重试操作耗资源
  • 只能对一个变量作原子操作

2.3应用场景

并发访问中存在频繁查询数据操作

2.4实现

总结

悲观锁是一种抢占式锁,获取资源后,对资源进行加锁,保证只有当前线程可进行操作,其它线程继续阻塞,等待当前线程处理完释放锁后,才可进行资源争夺。悲观锁适合于频繁更新的操作,比如数据库更新时表锁等。

乐观锁实际上并未对共享资源进行加锁,而是采用比较更新的(cas)机制,保证多线程之间共享资源的一致性。更新操作是一个不断重试的操作。乐观锁适合于频繁查询的操作。


未完待续…

猜你喜欢

转载自blog.csdn.net/sunyanxiong123/article/details/84642289