面试:java中的各种锁对比

news2024/11/24 14:11:23

共享锁

共享锁有CountDownLatch, CyclicBarrier, Semaphore, ReentrantReadWriteLock等

ReadWriteLock,顾名思义,是读写锁。它维护了一对相关的锁 — — “读取锁”和“写入锁”,一个用于读取操作,另一个用于写入操作。
“读取锁”用于只读操作,它是“共享锁”,能同时被多个线程获取。
“写入锁”用于写入操作,它是“独占锁”,写入锁只能被一个线程锁获取。
注意:不能同时存在读取锁和写入锁!

独占锁/排他锁

 java中的Synchronied和ReentrantLook 都是独占锁

悲观锁

顾名思义,是悲观的,觉得不锁柱的资源会被别人的线程抢走,所以悲观锁每次获取和修改数据都会锁定数据。

典型的悲观锁案例:synchronized关键词和Lock接口。

乐观锁

认为自己在操作资源时不会有其他线程干扰,所以不会锁定对象,只是在更新资源时会去对比一下我修改过的数据之间是否有其他线程修改过的数据。若无修改,此次修改正常,若有其他线程修改,则放弃此次修改,并选择报错或重试。这是一个基于冲突检测的并发策略,这种并发策略的实现不需要线程挂起,因此是非阻塞同步。乐观主义锁一般采用CAS算法实现。

常见的乐观锁实现方式有两种,分别是:1、版本号机制;2、CAS算法。

版本号机制:当然线程A需要更新数据值时,在读取数据的同时也会读取 version 值,在提交更新时,若刚才读取到的 version 值为当前数据库中的 version 值相等时才更新,否则重试更新操作,直到更新成功。

典型的乐观锁案例:

1、Java并发包Atomic原子类,

2、synchronized锁升级,

3、JDK1.8中的ConcurrentHashMap实现,完全重构了JDK1.7,不再使用分段锁,而是给数组中的每个头节点都加锁,并且用的是synchronized。整体采用CAS+synchronized来保证并发的安全性,

ConcurrentHashMap的put操作:

判断表是否为空,如果为空就初始化表initTable(),只有一个线程可以初始化成功。

如果已经初始化,则找到当前key所在桶是判断是否为空,若为空则通过CAS把新节点插入此位置casTabAt(),只有一个线程可以CAS成功

如果key所在桶不为空,则判断节点的hash值是否为-1,若为-1则说明当前数组正在扩容。

如果如果key所在桶不为空,且没在扩容,则给桶中的第一个节点对象加锁synchronized,然后判断是否是链表或者树,然后插入数据。

判断链表长度是否大于8,如果是链表转为红黑树。

自旋锁的定义

自旋锁指的是当线程获取不到资源时,不是进入阻塞状态,而是让当前的线程不停地执行空循环,直到循环条件被其他线程改变,进入临界区。

自旋锁:竞争锁的失败的线程,并不会真实的在操作系统层面挂起等待,而是JVM会让线程做 几个空循环(基于预测在不久的将来就能获得),在经过若干次循环后,如果可以获得锁,那么进入临界区,如果还不能获得锁,才会真实的将线程在操作系统层面进行挂起。 适用场景:自旋锁可以减少线程的阻塞,这对于锁竞争不激烈,且占用锁时间非常短的代码块 来说,有较大的性能提升,因为自旋的消耗会小于线程阻塞挂起操作的消耗。 如果锁的竞争激烈,或者持有锁的线程需要长时间占用锁执行同步块,就不适合使用自旋锁 了,因为自旋锁在获取锁前一直都是占用cpu做无用功,线程自旋的消耗大于线程阻塞挂起操作的消耗,造成cpu的浪费。

什么是自旋

很多synchronized里面的代码只是一些很简单的代码,执行时间非常快,此时等待的线程都加锁可能是一种不太值得的操作,因为线程阻塞涉及到用户态和内核态切换的问题。既然synchronized里面的代码执行得非常快,不妨让等待锁的线程不要被阻塞,而是在synchronized的边界做忙循环,这就是自旋。如果做了多次忙循环发现还没有获得锁,再阻塞,这样可能是一种更好的策略。
 

公平锁和非公平锁:

CPU在调度线程的时候是在等待队列里随机挑选一个线程,由于这种随机性所以是无法保证线程先到先得的(synchronized控制的锁就是这种非公平锁)。但这样就会产生饥饿现象,即有些线程(优先级较低的线程)可能永远也无法获取CPU的执行权,优先级高的线程会不断的强制它的资源。那么如何解决饥饿问题呢,这就需要公平锁了。公平锁可以保证线程按照时间的先后顺序执行,避免饥饿现象的产生。但公平锁的效率比较低,因为要实现顺序执行,需要维护一个有序队列。

synchronized控制的锁就是这种非公平锁;

ReentrantLock便是一种公平锁,通过在构造方法中传入true就是公平锁,传入false,就是非公平锁;

同个线程可以进入之前获得锁的同步代码块,这是可重入锁的核心思想了。

可重入锁:

可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。Java中ReentrantLock和synchronized都是可重入锁;

其他博客总结:

1、分门别类总结Java中的各种锁,让你彻底记住:

分门别类总结Java中的各种锁,让你彻底记住_Rain仰望的博客-CSDN博客

2、java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁:

java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁_朱清震的博客-CSDN博客_java 属性锁

3、下面是可重入和不可重入锁的示例:

因为不可重锁没有内置对象,所以需要我们自己去实现一个不可重入锁。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockTest {
	
	/**
	 * 不可重入锁
	 * 执行结果:方法1运行
	 */
//	MyLock lock = new MyLock();
	
	/**
	 * 可重入锁:同个线程可以进入之前获得锁的同步代码块,这是可重入锁的核心思想
	 * 执行结果:方法1运行  方法2运行
	 */
	Lock lock = new ReentrantLock();
	
	public static void main(String[] args) throws InterruptedException {
		new ReentrantLockTest().method1();
	}
	
	public void method1() throws InterruptedException {
		lock.lock();
		System.out.println("方法1运行");
		method2();
		lock.unlock();
	}
	
	public void method2() throws InterruptedException {
		lock.lock();
		System.out.println("方法2执行");
		lock.unlock();
	}
}

class MyLock{
	private boolean isLocked = false;
	public synchronized void lock() throws InterruptedException{
		while(isLocked){
			wait();
		}
		isLocked = true;
	}
	public synchronized void unlock() {
		isLocked = false;
		notify();
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/20722.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

D. Make It Round(贪心 贡献 数学)[Codeforces Round #834 (Div. 3)]

题目如下: 思路 or 题解: 我们先考虑如何操作使结尾有最多的 0 我们不难发现: 2 * 5 10 10 10 我们是否只需要考虑 2 与 5 的贡献就行了 答案是肯定的!!! 约定: cnt5因数5的个数cnt_5 因数 …

kubernetes集群安装Ingress-nginx

文章目录概述搭建环境版本对应关系yaml文件安装实操演示常见问题外链地址概述 Ingress 公开从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。 Kubernetes 通过 kube-proxy 服务实现了 Service 的对外发布及负载均衡,它的各…

2.3、传输方式

2.3、传输方式 2.3.1、串行&并行 2.3.3.1、串行传输 串行传输是指数据是一个比特一个比特依次发送的。因此,在发送端与接收端之间只需要一条数据传输线路即可 2.3.3.2、并行传输 一次发送 nnn 个比特。为此,在发送端和接收端之间需要有 nnn 条传输…

解决vscode各种异常格式化编译器配置

在vscode中创建vue文件时,若编辑代码时会出现间隔一段时间后自动的格式化内容,会很烦,经反复改查后无果,后来,对编辑器进行全面配置 首先原setting.json文件中的代码是这样的 { "files.autoSave": &qu…

定压补水装置 隔膜式定压补水装置

循环水中气体的来源及危害 A、气体来源 1、补水中夹带气体。 2、在定压不稳时吸入的气体。 3、放水时气体的侵入。 4、管道阀门等设备跑冒滴漏时侵入。 B、气体存在的危害 1、容易形成气阻,增加运营成本。 水中气体不及时排除,它所形成空气袋或气柱&am…

Vue学习(九)——混入

前言 混入(mixin)的使用非常简单,其实我原本打算直接写插件(plugin)的,但考虑到插件的使用范围也包括混入和自定义指令,还是先讲讲这两个的基本概念。 混入在我看来,就是给组件加上…

maya 卡通草地制作方法笔记

maya 卡通草地制作方法笔记 一、概述 maya制作草地的方法很多,有粒子替代种子法,painter笔刷法,xgen毛发模拟法,也有直接批量大量代理物体复制法等等。这次讨论的是用maya的painter笔刷法,审核制作卡通类简单的草地效…

Linux 进程概念 —— 冯 • 诺依曼体系结构

文章目录1. 冯诺依曼体系结构🍑 输入、输出设备🍑 中央处理器🍑 内存🍑 总线🍑 局部性原理🍑 总结2. 数据的流动过程1. 冯诺依曼体系结构 在 1945 年冯诺依曼和其他计算机科学家们提出了计算机具体实现的报…

URL和URI的区别

文章目录URLSchemeAuthorityPath to resourceParametersAnchorURL和URI参考URL 以下是 URL 的一些示例: https://developer.mozilla.org https://developer.mozilla.org/en-US/docs/Learn/ https://developer.mozilla.org/en-US/search?qURL这些 URL 中的任何一个…

[附源码]java毕业设计水库水面漂浮物WEB系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

攻防世界Check

Check 题目描述:套娃? 题目环境:https://download.csdn.net/download/m0_59188912/87097474 将图片放入winhex中打开,文件头与文件尾均正常,文件大小也正常。 判断为lsb隐写,查看三个颜色的plane 0通道&…

mysql复习【面试】

mysql复习【面试】前言mysql复习第08章 索引的创建与设计原则3.索引设计原则3.2哪些情况下适合创建索引3.4 哪些情况不适合创建索引第10章 索引优化与查询优化2.索引失效案例8.覆盖索引9. 如何给字符串添加索引10. 索引下推11. 普通索引 vs 唯一索引12.其他的优化策略13. 淘宝数…

深入浅出学习透析Nginx服务器的基本原理和配置指南「负载均衡篇」

负载均衡 之前的章节内容中【深入浅出学习透析Nginx服务器的基本原理和配置指南「初级实践篇 」】和 【深入浅出学习透析Nginx服务器的基本原理和配置指南「进阶实践篇」】,我们采用的代理仅仅指向一个服务器。但是网站在实际运营过程中,大部分都是以集群…

【万兴PDF专家】OCR引擎的离线安装方法,让你不受网速的折磨,PDF给OCR成可搜索的高级PDF,牛逼了我的万兴

一、问题背景 万兴PDF是一个很好用的PDF工具,它不仅可以实现PDF的浏览和批注常见功能,还具有OCR、压缩PDF,乃至批量化的功能。 因此,实在是一个非常值得花钱去买的PDF工具包!! 但是,软件里的O…

Prometheus与Grafana监控SpringBoot应用

Prometheus与Grafana监控SpringBoot应用 1.SpringBoot应用暴露端点 2.转换成Prometheus能解析得数据 3.向Prometheus注册时赋予项目名 docker部署 4701模板

七.STM32F030C8T6 MCU开发之TIMER模块级联组成32BIT计时器案例

七.STM32F030C8T6 MCU开发之TIMER模块级联组成32BIT计时器案例 文章目录七.STM32F030C8T6 MCU开发之TIMER模块级联组成32BIT计时器案例0.总体功能概述1.TIM硬件介绍1.1 TIM1/3级联硬件介绍1.1.1 主从模式介绍1.1.2 TIM1为主,TIM3为从,TIM3 的输入触发源选…

【计算机网络】习题(三)—— 数据链路层

【计算机网络】习题(三)—— 数据链路层2.数据链路层协议的功能不包括(). A.定义数据格式 B。提供结点之间的可靠传输 C.控制对物理传输介质的访问 D.为终端结点隐蔽物理传输的细节 2.D 主是是数据链路层的主要功能包…

SECCON CTF 2022 web复现

skipinx 知识点:qs 参数解析错误qs简介 一句话介绍就是:qs是负责url参数转化的js库,当然也可以说是查询字符串解析和字符串化库。 详细了解移步:https://www.npmjs.com/package/qs qs简单用法 例如:我们 url 参数…

NTPv4协议解析

前言 本文的撰写基于RFC5905.NTP 是时间网络控制协议,V4版本相交V3版本,修复了V3存在的一些问题。尤其是NTPV4的拓展时间戳鼓励使用浮动双数据类型,这样使得NTP能够更好的支持1ns的场景,轮询间隔也从上一代的最多1024s拓展到了36…

上位机通信标准-OPC

OPC通信,基于OPC的通信是一种通信整合方案,通过OPC标准,整合各类协议并统一化接口。 1、上位机通信环境 - 品牌、各类繁多 - 通信环境的统一:OPC 2、OPC - 什么是OPC:OLE for Process Control Windows插件&#x…