面试:java中的各种锁

news2025/4/5 1:38:56

共享锁

共享锁有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/19511.html

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

相关文章

java计算机毕业设计ssm建设路小学芙童币和芙童印章管理系统

项目介绍 随着移动互联网技术的迅速发展,时代对人们的知识水平和综合素质要求也越来越高了,各种教育管理系统层出不穷。其中以建设路小学吉祥物“芙童”为卡通原型设计的芙童印章、芙童币深受学生和老师们的喜爱。这是学校结合德育教学、少先队活动和社会实践活动为他们量身定…

Mybatis源码解析(六):一级缓存和二级缓存的优先级

Mybatis源码系列文章 手写源码(了解源码整体流程及重要组件) Mybatis源码解析(一):环境搭建 Mybatis源码解析(二):全局配置文件的解析 Mybatis源码解析(三):映射配置文件的解析 Mybatis源码解析(四):s…

Unity学习笔记[一] RollBall小游戏

目录 一、适配vs 二、初识Unity 2.1 unity核心模块 2.2 Unity基本操作和场景操作 2.3 世界坐标系和局部坐标系 2.4 工具栏 QWER 三、基础知识 3.1 基本组件 3.2 刚体组件 3.2.1 获取刚体组件 3.2.2 给刚体施加力 3.3 三维向量Vector3 3.4 通过按键控制左右运动 3…

【Pygame】 游戏开发 基础知识

【Pygame】 第一课 游戏开发 基础知识概述Pygame 的安装Pygame 基础命令pygame.locals 模块pygame.init()pygame.display.set_mode()案例Pygame 显示文字pygame.font.Font()fill()render()blit()pygame.display.update()案例显示英文显示中文概述 Pygame 是一个跨平台的 Pytho…

计算机网络 - 物理层数据链路层大题复习题

文章目录1、在下面给出的TCP/IP层次模型图示中填写空缺处①-⑤的协议名称。2、请写出在OSI的第几层分别处理下面的问题?3、试简述数据链路层的三个基本问题为什么都必须加以解决?4、收发两端之间的传输距离为100km,信号在媒体上的传播速率为2…

网络层协议数据单元-N_PDU

诊断协议那些事儿 关联文章: UDS的OSI模型 ISO14229各Part介绍:第三部分:CAN实施的统一诊断服务(UDSonCAN) UDS诊断网络层ISO15765-2(CAN) 功能寻址的注意事项 文章目录诊断协议那些事儿一、N_…

雅思词汇真经单词共3663个

雅思词汇真经 / Vocabulary for IELTS / 学为贵 赢未来 / 英语真经派学习法 一本书精通雅思词汇 / 刘洪波 编著 / 涵盖:雅思必备核心词汇刘洪波老师原创雅思考点词库 逻辑词群记忆法,一群一群记单词,快速备考无负责 时尚插图,趣味…

Golang实现小型CMS内容管理功能(一):Gin框架搭配Gorm实现增删查改功能

我自己开发了一款在线客服系统,最近一直琢磨把客服系统官网做好。因为访客来的人不少,大部分人可能就是看看官网界面就走了,怎样把这些访客留存下来,去测试试用客服系统,是我一直琢磨的问题。 官网是一个企业的门面&a…

PyQT6 pip install (三) 百篇文章学PyQT

本文章是百篇文章学PyQT的第三篇,本文讲述如何使用PIP安装PyQT6,PyQT6在安装过程中会遇到很多问题,博主在本篇文章中将遇到和踩过的坑总结出来,可以供大家参考,希望大家安装顺利。包括 安装、遇到问题的解决方案、怎么…

卷积运算与卷积核DLC

一、卷积运算 在数学上,卷积的定义是:两个函数在反转和位移后的乘积的积分,其公式表现为: 其中称g为过滤器,f为信号。 但是在深度学习中,卷积并不进行反转,而是直接进行逐元素的乘法和加法&…

【读书笔记】人月神话(一)

后续文章都是从本人的知乎博客上搬迁过来。 在软件领域,布鲁克斯博士的《人月神话》是一本关于大型项目管理的经典之作。这本书不仅对每一个软件行业的项目经理(PM)来说是一本必读读物,对每个软件行业的参与者(程序员,测试人员或者是创业者)…

详解c++---类和对象(三)

目录标题拷贝构造函数为什么会有该函数拷贝构造的特性第一个性质的详解第二个性质详解第三个性质的详解什么时候得自己写拷贝构造函数哪些场景会用到拷贝构造函数运算符重载函数为什么会有运算符重载运算符重载的形式>和>的运算符重载和的运算符的重载-和-的运算符重载运…

用anacnda创建虚拟环境用不用指定python版本

用anaconda创建了python虚拟环境以后,想用pycharm指定这个python解释器。 首先,在我创建虚拟环境并未指定python版本的情况下,在使用anaconda prompt的命令 conda create -n envs_name(未指定python版本)以后&#xff…

智能油井在线监控解决方案,第一时间掌握所有动态

随着物联网、云计算等技术的不断革新,物联网技术已经渗透到工业生产的方方面面。例如智能油井;油田地域广阔,分布着大量各种油井,油井开采设备的连续稳定运行是保证石油开采的首要条件。但是油井生产过程中,各井之间距…

C++ 多线程 线程安全队列设计

这是看《C并发编程实战》这本书学的,这里我要为这本书辟谣一下,虽然是这本书前面翻译得很烂,但是从第6章开始,应该是换了个人翻译,虽然还是能难懂,但是难懂的是代码逻辑,而不是语言逻辑&#xf…

MySQL8.0优化 - 锁 - 全局锁、死锁

文章目录学习资料锁的不同角度分类锁的分类图如下其他锁之:全局锁其他锁之:死锁概念产生死锁的必要条件如何处理死锁如何避免死锁学习资料 【MySQL数据库教程天花板,mysql安装到mysql高级,强!硬!-哔哩哔哩…

Java——继承下的抽象类与接口

文章目录壹、抽象类贰、接口前言: 我们前一章写了继承性,这一章节,一起来学习Java中的抽象类与接口相关知识。 壹、抽象类 1、定义:用关键字abstract修饰的类称为抽象类(abstract类)。 2、格式&#xff1…

进程调度例题解析

文章目录例题1 一个四道作业的操作系统中,设在一段时间内先后到达6个作业,它们的提交时间和运行时间见表例题2 一个具有两道作业的批处理系统,作业调度采用短作业优先的调度算法,进程调度采用以优先数为基础的抢占式调度算法&…

智慧矿山解决方案-最新全套文件

智慧矿山解决方案-最新全套文件一、建设背景二、建设思路智能矿山建设存在的问题1、行业上存在的问题2、承建商存在的问题3、矿井自身存在的问题三、建设方案四、获取 - 智慧矿山全套最新解决方案合集一、建设背景 采矿业是我国国民经济的基础和支柱产业,而矿山智慧…

云安全防护总体架构设计

安全需求和挑战 从风险管理的角度讲,主要就是管理资产、威胁、脆弱性 和防护措施及其相关关系,最终保障云计算平台的持续安全,以及 其所支撑的业务的安全。 云计算 平台是在传统 IT技术的基础上,增加了一个虚拟化层,并…