常见的锁策略(面试八股文)
1.乐观锁vs悲观锁
乐观锁:预测该场景中不太会出现锁冲突的情况。(后续做的工作会更少)
悲观锁:预测该场景非常容易出现锁冲突(后续做的工作会更多)
锁冲突:多个线程同时尝试去获得同一把锁,其中一个线程能够获取成功,其余线程阻塞等待
乐观锁和悲观锁是在加锁之前,对锁冲突概率的预测,决定开销的多少
2.重量级锁vs轻量级锁
重量级锁:加锁的开销是比较大的(花的时间多,占用的资源多),一个悲观锁很可能就是一个重量级锁(不绝对)
轻量级锁:加锁的开销比较小(花的时间少,占用的资源少),一个乐观锁很可能就是一个轻量级锁(不绝对)
.重量级和轻量级锁是在加锁之后对锁实践开销的考量
3.读写锁vs互斥锁
互斥锁:就是普通的锁,没有为读操作和写操作分开加锁,synchronized就是互斥锁
读写锁:把读操作加锁和写操作加锁分开了
因为多线程同时去读同一个变量不会涉及到线程安全问题
如果两个线程,一个线程读加锁,另一个线程也是读加锁,不会发生锁竞争(多线程并发执行的效率就会更高)
如果两个线程,一个线程写加锁,另一个线程也是写加锁,会发生锁竞争
如果两个线程,一个线程写加锁,另一个线程是读加锁,会发生锁竞争
在实践开发中,读操作的频率往往比写操作的频率高,所以通过读写锁可以大大提高程序运行的效率(因为在多个线程对同一个变量进行读取操作的时候不会发生锁竞争,是并发执行的)
4.自旋锁vs挂起等待锁
自旋锁:一种典型的轻量级锁的实现方式,线程在抢锁失败后会进入阻塞状态,要等到获得锁的线程释放锁才能去尝试获取锁,而自旋锁会在获取锁失败了以后,立即再尝试去获取锁,无限循环(一直不停的去尝试获取锁)这样一旦锁被其他线程释放,就能够第一时间获得锁。
优点:一旦锁被释放可以第一时间获得锁(对比挂起等待锁,获得锁的速度会快很多)
缺点:如果锁被其他线程持有的时间比较久,那么就会持续的消耗cpu资源(而挂起等待的时间是不消耗cpu的)
挂起等待锁:是重量级锁的一种典型表现,当出现锁冲突的时候,会牵扯到内核对于线程的调度,使冲突的线程出现挂起(阻塞等待)
5.公平锁vs非公平锁
假设三个线程A, B,C.A先尝试获取锁,获取成功.然后B再尝试获取锁,获取失败,阻塞等待;然后C也尝试获取锁,C也获取失败,也阻塞等待.
当线程A释放锁的时候,会发生啥呢?
公平锁:遵守"先来后到".B比C先来的.当A释放锁的之后,B就能先于C获取到锁
非公平锁:不遵守"先来后到".B和C都有可能获取到锁.
6.可重入锁和不可重入锁
有一个线程,针对同一个对象,连续加锁了两次,如果产生了死锁就是不可重入锁,如果没有产生死锁就是可重入锁
例子:
public synchronized void increase(){synchronized(this){count++;}
}
如上述代码,调用increase方法后会在同一个线程中对同一个对象进行两次加锁,如果是不可重入锁的话,在调用increase方法对类对象进行加锁了以后,执行increase方法中的程序再对类对象进行加锁就会发生阻塞等待,一直要阻塞到第一个对类对象加锁的线程释放锁,但要执行完该线程又需要获得锁了以后才能向下执行,所以程序就卡在了第二次对类对象加锁这里,也就形成了死锁。
死锁的三种经典情况
1.一个线程一把锁,但是是不可重入锁,该线程针对这个锁连续加锁两次,就会出现死锁
2.两个线程,两把锁,这两把线程先分别获取到一把锁,然后再同时尝试获取对方的那把锁
通过下面的代码可以直观的看到该情况
ublic class Demo1 {public static void main(String[] args) {Object blocer1=new Object();Object blocer2=new Object();Thread t1=new Thread(()->{synchronized(blocer1){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized(blocer2){System.out.println("t1线程获取两把锁");}}});Thread t2=new Thread(()->{synchronized(blocer2){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized(blocer1){System.out.println("t2线程获取两把锁");}}});t1.start();t2.start();}
}
3.N个线程M把锁,N个线程中每个线程都会对多把锁进行加锁,而且加的锁是有重复的,这样在莫种特殊情况下就会形成死锁
产生死锁的四个必要条件
1.互斥使用,一个线程获取到一把锁了以后,其他线程就不能去获取这把锁(实际使用的锁,一般都是互斥的,锁的基本特征)
2.不可抢占,锁只能是持有者主动释放,而不是被其他其他线程直接抢走(也是锁的基本特征)
3.请求和保持,当一个线程去尝试获取多把锁,在获取第二把锁的时候会保持对第一把锁的获取状态(取决于代码结构)
4.循环等待,t1尝试获取locker2,需要t2执行完,释放locker2,t2尝试获取locker1,需要t1执行完,释放locker1,发生了死循环(取决于代码结构)
解决死锁的有效方法
解决死锁主要是针对循环等待这方面来进行解决
当每个线程要获取多把锁,先针对锁进行编号,约定,每个线程如果要获取多把锁,必须先获取编号小的锁,后获取编号大的锁。
只要所有线程加锁的顺序,都严格遵守上述顺序,就一定不会出现循环等待,就解决了死锁
synchronized采用的锁策略
1.即是悲观锁也是乐观锁,即是重量级锁也是轻量级锁,是自适应的
2.重量级锁部分是根据系统的互斥锁实现的,轻量级锁部分是根据自旋锁实现的
3.非公平锁(不会遵循先来后到,锁释放后,那个线程获得锁,各凭本事)
4.可重入锁,同一个线程可以多次获取同一把锁(内部会记录哪个线程拿了锁,记录引用计数,要是是同一个线程拿锁,计数器就加一,此时该线程要解锁的话,计数器就减一,直到1计数器为0才真正解锁)
5.不是读写锁,是普通的互斥锁
synchronized的自适应过程
代码写了一个synchronized之后,这里可能会产生一系列的自适应过程:无锁->偏向锁->轻量级锁->重量级锁
一开始是无锁的,加了synchronized后就对程序加了偏向锁,偏向锁,不是真的加锁,而只是做了一个标记,如果有别的线程来竞争锁了,才会真的加锁,如果没有别的线程竞争,就自始至终都不会真的加锁
偏向锁真的加锁以后就是轻量级锁,但是后续如果竞争这把锁的线程越来越多了(锁冲突更激烈了),从轻量级锁升级成了重量级锁
相关文章:

常见的锁策略(面试八股文)
1.乐观锁vs悲观锁 乐观锁:预测该场景中不太会出现锁冲突的情况。(后续做的工作会更少) 悲观锁:预测该场景非常容易出现锁冲突(后续做的工作会更多) 锁冲突:多个线程同时尝试去获得同一把锁&…...

SO_KEEPALIVE、TCP_KEEPIDLE、TCP_KEEPINTVL、保活包
SO_KEEPALIVE SO_KEEPALIVE 是一个套接字选项,用于设置是否启用 keepalive 机制。在这段代码中没有涉及到 SO_KEEPALIVE 选项的设置。 当 SO_KEEPALIVE 被设置为非零值时,表示启用 keepalive 机制。keepalive 是一种用于检测连接是否仍然有效的机制。通…...

【phaser微信抖音小游戏开发005】画布上添加图片
特别注意:真机模拟的时候,尽量使用网络图片资源,不要在小程序源文件里面使用图片,会出现真机加载不成功,小程序包体积过大的问题。我们学习过程中,只是作为演示使用。 推荐使用场景: 背景图片…...

【设计模式——学习笔记】23种设计模式——外观模式Facade(原理讲解+应用场景介绍+案例介绍+Java代码实现)
文章目录 案例引入介绍基本介绍类图出场角色 案例实现案例一类图代码实现 案例二类图代码实现 外观模式在Mybatis源码中的应用总结文章说明 案例引入 在家庭影院中,要享受一场电影,需要如下步骤: 直接用遥控器:统筹各设备开关开…...

消息队列 -提供上层服务接口
目录 前言封装数据库封装内存操作内存的设计思想 应答模式 代码实现测试代码 前言 我们之前已经将 数据库 的操作 和文件的操作 都完成了, 但是对于上层调用来说, 并不关心是于数据库中存储数据还是往文件中存储数据, 因此 我们提供一个类, 封装一下 上述俩个类中的操作, 并将…...

maven引入本地jar包的简单方式【IDEA】【SpringBoot】
前言 想必点进来看这篇文章的各位,都是已经习惯了Maven从中央仓库或者阿里仓库直接拉取jar包进行使用。我也是🤡🤡。 前两天遇到一个工作场景,对接三方平台,结果对方就是提供的一个jar包下载链接,可给我整…...

【爬虫逆向案例】某易云音乐(评论)js逆向—— params、encSecKey解密
声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢! 【爬虫逆向案例】某易云音乐(评论)js逆向—— params、encSecKey解密 1、前言2、行动…...

【uni-app】【Android studio】手把手教你运行uniapp项目到Android App
运行到Android App基座 选择运行到Android App基座 选择运行项目 1、连接手机,在手机上选择 传输文件。 2、打开 设置-> 关于本机 -> 版本信息->连续点击4-5次版本号 ,输入手机密码,系统就进入了开发者模式。 3、设置 > 其他设…...

多线程(JavaEE初阶系列6)
目录 前言: 1.什么是线程池 2.标准库中的线程池 3.实现线程池 结束语: 前言: 在上一节中小编带着大家了解了一下Java标准库中的定时器的使用方式并给大家实现了一下,那么这节中小编将分享一下多线程中的线程池。给大家讲解一…...

shell清理redis模糊匹配的多个key
#!/bin/bash# 定义Redis服务器地址和端口 REDIS_HOST"localhost" REDIS_PORT6380# 获取匹配键的数量 function get_matching_keys() {local key_pattern"$1"redis-cli -h $REDIS_HOST -p $REDIS_PORT -n 0 KEYS "$key_pattern" }# 删除匹配的键 …...

【电网异物检测硕士论文摘抄记录】电力巡检图像中基于深度学习的异物检测方法研究
根据国家电力行业发展报告统计,截止到 2018 年,全国电网 35 千伏及以上的输电线路回路长度达到 189 万千米,220 千伏及以上输电线路回路长度达73 万千米。截止到 2015年,根据国家电网公司的统计 330 千伏及以上输电线路故障跳闸总…...

C++共享数据的保护
虽然数据隐藏保护了数据的安全性,但各种形式的数据共享却又不同程度地破坏了数据的安全。因此,对于既需要共享有需要防止改变的数据应该声明为常量。因为常量在程序运行期间不可改变,所以可以有效保护数据。 1.常对象 常对象:它…...

MyBatisPlus学习记录
MyBatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率 MyBatisPlus简介 入门案例 创建新模块,选择Spring初始化,并配置模块相关基础信息选择当前模块需要使用的技术集(仅选择MySQL …...

如何开启一个java微服务工程
安装idea IDEA常用配置和插件(包括导入导出) https://blog.csdn.net/qq_38586496/article/details/109382560安装配置maven 导入source创建项目 修改项目编码utf-8 File->Settings->Editor->File Encodings 修改项目的jdk maven import引入…...

libhv之hio_t分析
上一篇文章解析了fd是怎么与io模型关联。其中最主要的角色扮演者:hio_t 1. hio_t与hloop的关系 fd的值即hio_t所在loop ios变量中所在的index值。 hio_t ios[fd] struct hloop_s { ...// ios: with fd as array.index//io_array保存了和hloop关联的所有hio_t&…...

C语言的转义字符
转义字符也叫转移序列,包含如下: 转移序列 \0oo 和 \xhh 是 ASCII 码的特殊表示。 八进制数示例: 代码: #include<stdio.h> int main(void) {char beep\007;printf("%c\n",beep);return 0; }结果: …...

【腾讯云 Cloud Studio 实战训练营】CloudStudio体验真正的现代化开发方式,双手插兜不知道什么叫对手!
CloudStudio体验真正的现代化开发方式,双手插兜不知道什么叫对手! 文章目录 CloudStudio体验真正的现代化开发方式,双手插兜不知道什么叫对手!前言出现的背景一、CloudStudio 是什么?二、CloudStudio 的特点三、CloudS…...

Pandas时序数据分析实践—时序数据集
1. 跑步运动为例,对运动进行时序分析 时序数据是指时间序列数据,是按照时间顺序排列的数据集合,每个数据点都与一个特定的时间戳相关联。在跑步活动中,我们可以将每次跑步的数据记录作为一个时序数据样本,每个样本都包…...

use strict 是什么意思?使用它区别是什么?
use strict 是什么意思?使用它区别是什么? use strict 代表开启严格模式,这种模式下使得 JavaScript 在更严格的条件下运行,实行更严格解析和错误处理。 开启“严格模式”的优点: 消除 JavaScript 语法的一些不合理…...

常见OOM异常分析排查
常见OOM异常分析排查 Java内存溢出Java堆溢出原因解决思路总结 Java内存溢出 java堆用于存储对象实例,如果不断地创建对象,并且保证GC Root到对象之间有可达路径,垃圾回收机制就不会清理这些对象,对象数量达到最大堆的容量限制后就会产生内存溢出异常. Java堆溢出原因 无法在…...

kubernetes网络之网络策略-Network Policies
Kubernetes 中,Network Policy(网络策略)定义了一组 Pod 是否允许相互通信,或者与网络中的其他端点 endpoint 通信。 NetworkPolicy 对象使用标签选择Pod,并定义规则指定选中的Pod可以执行什么样的网络通信࿰…...

交换机VLAN技术和实验(eNSP)
目录 一,交换机的演变 1.1,最小网络单元 1.2,中继器(物理层) 1.3,集线器(物理层) 1.4,网桥(数据链路层) 二,交换机的工作行为 2.…...

8.Winform界面打包成DLL提供给其他的项目使用
背景 希望集成一个Winform的框架,提供权限菜单,根据权限出现各个Winform子系统的菜单界面。不希望把所有的界面都放放在同一个解决方案下面。用各个子系统建立不同的解决方案,建立代码仓库,进行管理。 实现方式 将Winform的UI界…...

海量数据存储组件Hbase
hdfs hbase NoSQL数据库 支持海量数据的增删改查 基于Rowkey查询效率特别高 kudu 介于hdfs和hbase之间 hbase依赖hadoopzookeeper,同时整合框架phoenix(擅长读写),hive(分析数据) k,v 储存结构 稀疏的(为空的不存…...

(一)基于Spring Reactor框架响应式异步编程|道法术器
在执行程序时: 通常为了提供性能,处理器和编译器常常会对指令进行重排序。 从排序分为编译器重排序和处理器重排序两种 * (1)编译器重排序: 编译器保证不改变单线程执行结构的前提下,可以调整多线程语句执行顺序; * (2)处理器重排序: 如果不存在数据依赖…...

Vue3 让localstorage变响应式
Hook使用方式: import {useLocalStore} from "../js/hooks"const aauseLocalStore("aa",1) 需求一: 通过window.localStorage.setItem可以更改本地存储是,还可以更新aa的值 window.localStorage.setItem("aa&quo…...

【深度学习】InST,Inversion-Based Style Transfer with Diffusion Models,论文,风格迁移,实战
代码:https://github.com/zyxElsa/InST 论文:https://arxiv.org/abs/2211.13203 文章目录 AbstractIntroductionRelated WorkImage style transferText-to-image synthesisInversion of diffusion models MethodOverview ExperimentsComparison with Sty…...

【CSS】3D卡片效果
效果 index.html <!DOCTYPE html> <html><head><title> Document </title><link type"text/css" rel"styleSheet" href"index.css" /></head><body><div class"card"><img…...

OrderApplication
目录 1 OrderApplication 2 /// 查询订单 2.1.1 //补充商品单位 2.1.2 //补充门店名称 2.1.3 //补充门店名称 2.1.4 //订单售后 2.1.5 //订单项售后 OrderApplication...

如何在保健品行业运用IPD?
保健品是指能调节机体功能,不以治疗为目的,并且对人体不产生任何急性、亚急性或者慢性危害的产品。保健品是食品的一个种类,具有一般食品的共性,其含有一定量的功效成分,能调节人体的机能,具有特定的功效&a…...