锁专题(1)java 常见锁介绍,高级程序员必知必会
序言Java提供了种类丰富的锁 , 每种锁因其特性的不同 , 在适当的场景下能够展现出非常高的效率 。
本文旨在对锁相关源码(本文中的源码来自JDK 8)、使用场景进行举例 , 为读者介绍主流锁的知识点 , 以及不同的锁的适用场景 。
Java中往往是按照是否含有某一特性来定义锁 , 我们通过特性将锁进行分组归类 , 再使用对比的方式进行介绍 , 帮助大家更快捷的理解相关知识 。
下面给出本文内容的总体分类目录:
文章插图
输入图片说明
悲观锁、乐观锁乐观锁与悲观锁是一种广义上的概念 , 体现了看待线程同步的不同角度 。 在Java和数据库中都有此概念对应的实际应用 。
先说概念 。 对于同一个数据的并发操作 , 悲观锁认为自己在使用数据的时候一定有别的线程来修改数据 , 因此在获取数据的时候会先加锁 , 确保数据不会被别的线程修改 。 Java中 , synchronized关键字和Lock的实现类都是悲观锁 。
而乐观锁认为自己在使用数据时不会有别的线程修改数据 , 所以不会添加锁 , 只是在更新数据的时候去判断之前有没有别的线程更新了这个数据 。 如果这个数据没有被更新 , 当前线程将自己修改的数据成功写入 。 如果数据已经被其他线程更新 , 则根据不同的实现方式执行不同的操作(例如报错或者自动重试) 。
悲观锁(Pessimistic Lock)顾名思义 , 就是很悲观 , 每次去拿数据的时候都认为别人会修改 , 所以每次在拿数据的时候都会上锁 , 这样别人想拿这个数据就会 block 直到它拿到锁 。传统的关系型数据库里边就用到了很多这种锁机制 , 比如行锁 , 表锁等 , 读锁 , 写锁等 , 都是在做操作之前先上锁 。
乐观锁(Optimistic Lock)乐观锁在Java中是通过使用无锁编程来实现 , 最常采用的是CAS算法 , Java原子类中的递增操作就通过CAS自旋实现的 。
顾名思义 , 就是很乐观 , 每次去拿数据的时候都认为别人不会修改 , 所以不会上锁 , 但是在更新的时候会判断一下在此期间别人有没有去更新这个数据 , 可以使用版本号等机制 , 即对数据做版本控制 。乐观锁适用于多读的应用类型 , 这样可以提高吞吐量 , 像数据库如果提供类似于 write_condition 机制的其实都是提供的乐观锁 。
文章插图
输入图片说明
适合场景根据从上面的概念描述我们可以发现:
悲观锁适合写操作多的场景 , 先加锁可以保证写操作时数据正确 。
乐观锁适合读操作多的场景 , 不加锁的特点能够使其读操作的性能大幅提升 。
实际例子光说概念有些抽象 , 我们来看下乐观锁和悲观锁的调用方式示例:
//悲观锁的调用方式public synchronized void testMethod() (//操作同步资源)// ReentrantLock private ReentrantLock lock = new ReentrantLock();public void modifyPublicResources() (lock. lock();//操作同步资源lock.unlock();)// 乐观锁的调用方式private AtomicInteger atomicInteger = new AtomicInteger();//需要保证多个线程使用同一个AtomicIntegeratomicInteger.incrementAndGet();
通过调用方式示例 , 我们可以发现悲观锁基本都是在显式的锁定之后再操作同步资源 , 而乐观锁则直接去操作同步资源 。
那么 , 为何乐观锁能够做到不锁定同步资源也可以正确的实现线程同步呢?
我们通过介绍乐观锁的主要实现方式 “CAS” 的技术原理来为大家解惑 。
CAS 技术详解
自旋锁 VS 适应性自旋锁在介绍自旋锁前 , 我们需要介绍一些前提知识来帮助大家明白自旋锁的概念 。
阻塞阻塞或唤醒一个Java线程需要操作系统切换CPU状态来完成 , 这种状态转换需要耗费处理器时间 。 如果同步代码块中的内容过于简单 , 状态转换消耗的时间有可能比用户代码执行的时间还要长 。
在许多场景中 , 同步资源的锁定时间很短 , 为了这一小段时间去切换线程 , 线程挂起和恢复现场的花费可能会让系统得不偿失 。 如果物理机器有多个处理器 , 能够让两个或以上的线程同时并行执行 , 我们就可以让后面那个请求锁的线程不放弃CPU的执行时间 , 看看持有锁的线程是否很快就会释放锁 。
而为了让当前线程“稍等一下” , 我们需让当前线程进行自旋 , 如果在自旋完成后前面锁定同步资源的线程已经释放了锁 , 那么当前线程就可以不必阻塞而是直接获取同步资源 , 从而避免切换线程的开销 。 这就是自旋锁 。
- 现状|程序员现状揭秘:平均年薪20.36万,Java人才需求量最大
- 苹果|iPhone13迎来变化!或回归指纹解锁,这几点备受用户喜爱
- 自动任务|赶在三星 S21 发布之前实现语音解锁
- 线下连锁商|暴涨130%!荷兰、西班牙、比利时百年商超在考拉海购逆势增长
- 长安街|北京 长安街西城段将来单车无法落锁
- 程序员学英语第1天——JavaScript 程序测试的介绍1
- 三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经
- 《深入理解Java虚拟机》:对象创建、布局和访问全过程
- 现场|逛展看未来丨展会现场还能这么玩?带你解锁萌娃的逛展“姿势”
- iPhone13迎来变化!或回归指纹解锁,这几点备受用户喜爱