您真的了解Java中的锁吗?这7种不同维度下的锁知道吗?
写在开头
在上几篇博文中,我们聊到过volatile关键字,用它修饰变量可以保证可见性与有序性,但它并不是锁,在使用时并不会阻塞线程,且不保证原子性,属于一种轻量级、高效的同步方式,因此,如果我们的使用场景仅需要保持可见性或者有序性,那可选择volatile,但如果必须保证原子性的话,volatile就不行了。
在Java多线程中,想真正的保证线程的安全,离不开一个东西,那就是 锁
!我们今天就一起来学习一下Java中的锁,以及常见锁的分类。
认识锁
很多面试官在问到Java锁的时候,往往都会这样开头
同学,你真的了解Java中的锁吗?
在Java中锁是一种非常重要的同步机制,经过前面的学习我们了解到,在并发编程中,经常会遇到多个线程访问同一个共享资源,当多个线程同时对共享资源操作写时,会导致数据不一致。通过锁的同步机制,可以确保在某一时刻只有一个线程能够访问特定的代码块或对象。
Java中实现锁的历程
早在jdk1.5之前就已经引入了synchronized 关键字,这个单词翻译成中文即为“同步”之意, Java 早期版本中,synchronized 属于 重量级锁,效率低下;不过,在 Java 6 之后, synchronized 引入了大量的优化如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销,这些优化让 synchronized 锁的效率提升了很多。JDK 1.5 开始,引入了并发工具包 java.util.concurrent.locks.Lock,让锁的功能更加丰富。
常用的锁
- synchronized 关键字锁定代码库
- 可重入锁 java.util.concurrent.lock.ReentrantLock
- 重复读写锁 java.util.concurrent.lock.ReentrantReadWriteLock
主流锁的分类
现在锁的分类根据不同维度大致分有7类,话不多说,先上一个思维导图便于记忆!
悲观锁 / 乐观锁
悲观锁:一律会对代码块进行加锁,如 synchronized、java.util.concurrent.locks.ReentrantLock;
乐观锁:默认不会进行并发修改,通常采用 CAS 算法不断尝试更新;
适应场景:悲观锁适合写操作较多的场景,乐观锁适合读操作较多的场景
自旋锁
自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环占有、浪费 CPU 资源。
偏向锁 / 轻量级锁 / 重量级锁
JDK 1.5 之后新增锁的升级机制,提升性能。通过 synchronized 加锁后,一段同步代码一直被同一个线程所访问,那么该线程获取的就是偏向锁;偏向锁被一个其他线程访问时,Java 对象的偏向锁就会升级为轻量级锁;再有其他线程会以自旋的形式尝试获取锁,不会阻塞,自旋一定次数仍然未获取到锁,就会膨胀为重量级锁
公平锁 / 非公平锁
公平锁:多个线程按照申请顺序来获取锁。如java.util.concurrent.lock.ReentrantLock.FairSync;
非公平锁:指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程先获得锁。如 synchronized、java.util.concurrent.lock.ReentrantLock.NonfairSync。
可重入锁
指在同一个线程在外层方法获取锁的时候,进入内层方法会自动获取锁。JDK 中基本都是可重入锁,避免死锁的发生。
独享锁 / 共享锁
独享锁指锁一次只能被一个线程所持有。synchronized、java.util.concurrent.locks.ReentrantLock 都是独享锁;
共享锁:指锁可被多个线程所持有。ReadWriteLock 返回的 ReadLock 就是共享锁。
除了以上这6种锁之外,还有的面试题中提到了粗粒度锁与细粒度锁
粗粒度锁 / 细粒度锁
粗粒度锁:就是把执行的代码块都锁定;
细粒度锁:就是锁住尽可能小的代码块,java.util.concurrent.ConcurrentHashMap 中的分段锁就是一种细粒度锁;
粗粒度锁和细粒度锁是相对的,没有什么标准。
总结
OK,今天关于锁的介绍就写到这里啦,本文先做一个总体上的概括,在后续的更新中会做详细介绍呀!
结尾彩蛋
如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏呀。原创不易,转载请联系Build哥!
如果您想与Build哥的关系更近一步,还可以关注“JavaBuild888”,在这里除了看到《Java成长计划》系列博文,还有提升工作效率的小笔记、读书心得、大厂面经、人生感悟等等,欢迎您的加入!
您真的了解Java中的锁吗?这7种不同维度下的锁知道吗?的更多相关文章
- Java中获取键盘输入值的三种方法
Java中获取键盘输入值的三种方法 Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值 ...
- Java中从控制台输入数据的几种常用方法
Java中从控制台输入数据的几种常用方法 一.使用标准输入串System.in //System.in.read()一次只读入一个字节数据,而我们通常要取得一个字符串或一组数字 //System.in ...
- Java中的ReentrantLock和synchronized两种锁定机制的对比
问题:多个访问线程将需要写入到文件中的数据先保存到一个队列里面,然后由专门的 写出线程负责从队列中取出数据并写入到文件中. http://blog.csdn.net/top_code/article/ ...
- Java中Elasticsearch 实现分页方式(三种方式)
目录 ES 简介 ES 的特点: 一.from + size 浅分页 二.scroll 深分页 scroll删除 三.search_after 深分页 ES 简介 Elasticsearch 是一个基 ...
- Java中的ReentrantLock和synchronized两种锁机制的对比
原文:http://www.ibm.com/developerworks/cn/java/j-jtp10264/index.html 多线程和并发性并不是什么新内容,但是 Java 语言设计中的创新之 ...
- 你真的了解JAVA中与Webservice相关的规范和实现吗?
非常多人在项目中使用Webservice,仅仅是知道怎样公布Webservice,怎样调用Webservice,但真要论其来龙去脉,还真不一定清楚. 一切一切还要从我们伟大的sun公司规范说起. JA ...
- Java内存管理-你真的理解Java中的数据类型吗(十)
勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 作为Java程序员,Java 的数据类型这个是一定要知道的! 但是不管是那种数据类型最 ...
- 你真的知道Java中boolean类型占用多少个字节吗?
为什么要问这个问题,首先在Java中定义的八种基本数据类型中,除了其它七种类型都有明确的内存占用字节数外,就boolean类型没有给出具体的占用字节数,因为对虚拟机来说根本就不存在 boolean 这 ...
- 你真的理解Java中的try/catch/finally吗?
看几个例子,回顾一下执行顺序 例子1 无异常,finally中的return会导致提前返回 public static String test() { try { System.o ...
- 你真的了解JAVA中对象和类、this、super和static关键字吗
作者:小牛呼噜噜 | https://xiaoniuhululu.com 计算机内功.JAVA底层.面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 目录 Java对象究竟是什么? 创建对象的过程 ...
随机推荐
- [Docker] Dockerfile常用保留字
FROM 基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板.第一条必须是from MAINTAINER 镜像维护者的姓名和邮箱地址 RUN 容器构建时需要运行的命令,也就是在 do ...
- RAPTOR:递归摘要与树形检索的结合,提升RAG检索性能
RAPTOR:递归摘要与树形检索的结合,提升RAG检索性能 来源:ICLR'24 https://arxiv.org/pdf/2401.18059.pdf 随着 LLM 技术的发展,RAG 的价值也来 ...
- 从零开始学正则(七:终章),详解常用正则API与你可能不知道的正则坑
壹 ❀ 引 花了差不多半个月的晚上时间,正则入门学习也步入尾声了,当然正则的学习还将继续.不得不说学习成效非常明显,已能看懂大部分正则以及写出不太复杂的正则,比如帮组长写正则验证文件路径正确性,再如 ...
- Laravel入坑指南(5)——请求与响应
作为互联网典型的Web应用,接收用户请求的数据,并将处理的结果向用户进行响应,是最基础也是最必备的功能.在原生的PHP中,我们常用$_POST.$_GET.$_REQUEST和$_FILES对不同的请 ...
- Java设计模式-适配器模式Adapter
介绍 适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本 因接口不匹配不能一起工作的两个类可以协同工作.其别名为包装器(Wrapper ...
- RAID 10磁盘阵列实践
RAID概述 RAID技术通过把多个硬盘设备组合成一个容量更大.安全性更好的磁盘阵列,利用分散读写技术来提升磁盘阵列整体的性能,同时把多个重要数据的副本同步到不同的物理硬盘设备上,从而起到了非常好的数 ...
- yum源配置脚本
# yum源配置脚本 #!/bin/bash mkdir /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bac ...
- 手写web框架
重新认识HTTP http请求报文包含三个部分(请求行 + 请求头 + 请求体) 请求行 请求行包含三个内容: method + request-URI + http-version -- 例如 GE ...
- 03、Etcd 客户端常用命令
上一讲我们安装 etcd 服务端,这一讲我们来一起学学如何使用 etcd 客户端常见的命令.文章内容来源于参考资料,如若侵权,请联系删除,谢谢. etcd可通过客户端命令行工具 etcdctl 对et ...
- 最经典的TCP性能问题
目录 问题描述 问题的原因 什么是delay ack 什么是Nagle算法 如果client启用Nagle,并且server端启用了delay ack会有什么后果呢? 再来看一个经典例子和数据分析 回 ...