JUC并发编程与源码分析学习笔记(二)

二十九、多线程锁之线程锁知识概述

说说Java“锁”事

从轻松的乐观锁和悲观锁开讲

通过8种情况演示锁运行案例,看看我们到底锁的是什么

公平锁和非公平锁

可重入锁(又名递归锁)

死锁及排查

写锁(独占锁)/读锁(共享锁)

自旋锁SpinLock

无锁->独占锁->读写锁->邮戳锁

无锁->偏向锁->轻量锁->重量锁

大厂面试题复盘

并发编程高级面试解析

一、Synchronized相关问题

1、Synchronized用过吗,其原理是什么?

2、你刚才提到获取对象的锁,这个“锁”到底是什么?如何确定对象的锁?

3、什么是可重入性,为什么说Synchronized是可重入锁?

4、JVM对Java的原生锁做了哪些优化?

5、为什么说Synchronized是非公平锁?

6、什么是锁消除和锁粗化?

7、为什么说Synchronized是一个悲观锁?乐观锁的实现原理又是什么?什么是CAS,它有

8、乐观锁一定就是好的吗?

二、可重入锁ReentrantLock及其他显示锁相关问题

1、跟Synchronized相比,可重入锁ReentrantLock其实现原理有什么不同?

2、那么请谈谈AQS框架是怎么回事儿?

3、请尽可能详尽地对比下Synchronized和ReentrantLock的异同。

4、ReentrantLock是如何实现可重入性的?

1、你怎么理解java多线程的?怎么处理并发?线程池有那几个核心参数?

2、Java加锁有哪几种锁?我先说了synchronized,刚讲到偏向锁,他就不让我讲了

3、简单说说lock

4、hashmap的实现原理?hash冲突怎么解决?为什么使用红黑树?

5、spring里面都使用了哪些设计模式?循环依赖怎么解决?

6、项目中哪个地方用了countdownlatch,怎么使用的?

三十、多线程锁之悲观锁和乐观锁介绍

悲观锁(狼性锁):认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改

synchronized关键字和Lock的实现类都是悲观锁

适合写操作多的场景,先加锁可以保证写操作时数据正确。

显示的锁定之后再操作同步资源

乐观锁(佛系锁):认为自己在使用数据时不会有别的线程修改数据或资源,所以不会添加锁。

在Java中是通过使用无锁编程来实现,只是在更新数据的时候去判断,之前有没有别的线程更新了这个数据。

如果这个数据没有被更新,当前线程将自己修改的数据成功写入。

如果这个数据已经被其它线程更新,则根据不同的实现方式执行不同的操作,比如放弃修改、重试抢锁等等

判断规则

1 版本号机制Version

2 最常采用的是CAS算法,Java原子类中的递增操作就通过CAS自旋实现的。

适合读操作多的常见,不加锁的特点能够使其读操作的性能大幅度提升。

乐观锁则直接去操作同步资源,是一种无锁算法,得之我幸不得我命,再努力就是一句话:

乐观锁一般有两种实现方式

采用Version版本号机制

CAS(Compare-and-Swap,即比较并替换)算法实现

伪代码说明

三十一、多线程锁之8锁案例编码演示

【强制】高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。

1、(代码)locks目录下:Lock8Demo.java

package com.nanjing.juc.locks;import java.util.concurrent.TimeUnit;/*** 多线程锁之8锁案例编码演示** @author xizheng* @date 2023-08-14 15:22:42*/
class Phone{public static synchronized void sendEmail(){try {TimeUnit.SECONDS.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("-----sendEmail");}public static synchronized void sendSMS(){System.out.println("-----sendSMS");}public void hello(){System.out.println("------hello");}
}/*** 题目:谈谈你对多线程锁的理解,8锁案例说明* 口诀:线程   操作  资源类* 8锁案例说明:* 1 标准访问有ab两个线程,请问先打印邮件还是短信* 2 sendEmail方法中加入暂停3秒钟,请问先打印邮件还是短信* 3 添加一个普通的hello方法,请问先打印邮件还是hello* 4 有两部手机,请问先打印邮件还是短信* 5 有两个静态同步方法,有1部手机,请问先打印邮件还是短信* 6 有两个静态同步方法,有2部手机,请问先打印邮件还是短信* 7 有1个静态同步方法,有1个普通同步方法,有1部手机,请问先打印邮件还是短信* 8 有1个静态同步方法,有1个普通同步方法,有2部手机,请问先打印邮件还是短信** 笔记总结:* 1-2* *  * 一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,* *  * 其它的线程都只能等待,换句话说,某一个时刻内,只能有唯一的一个线程去访问这些synchronized方法* *  * 锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法* 3-4* *  * 加个普通方法后发现和同步锁无关* *  * 换成两个对象后,不是同一把锁了,情况立刻变化。** 5-6 都换成静态同步方法后,情况又变化* 三种 synchronized 锁的内容有一些差别:* 对于普通同步方法,锁的是当前实例对象,通常指this,具体的一部部手机,所有的普通同步方法用的都是同一把锁->实例对象本身,* 对于静态同步方法,锁的是当前类的Class对象,如Phone.class唯一的一个模板* 对于同步方法块,锁的是 synchronized括号内的对象** 7-8*    当一个线程视图访问同步代码时它首先必须得到锁,正常退出或抛出异常时必须释放锁。* *  ** *  * 所有的普通同步方法用的都是同一把锁-实例对象本身,就是new出来的具体实例对象本身,本类this* *  * 也就是说如果一个实例对象的普通同步方法获取锁后,该实例对象的其他普通同步方法必须等待获取锁的方法释放锁后才能获取锁。* *  ** *  * 所有的静态同步方法用的也是同一把锁-类对象本身,就是我们说过的唯一模板Class* *  * 具体实例对象this和唯一模板Class,这两把锁是两个不同的对象,所以静态同步方法与普通同步方法之间是不会有竞态条件的* *  * 但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁才能获取锁。*/
public class Lock8Demo {public static void main(String[] args) {Phone phone = new Phone();Phone phone2 = new Phone();new Thread(() -> {phone.sendEmail();},"a").start();//暂停毫秒,保证a线程先启动try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {
//            phone.sendSMS();
//            phone.hello();phone2.sendSMS();},"b").start();}
}

三十三、多线程锁之synchronized字节码分析

synchronized有三种应用方式

8种锁的案例实际体现在3个地方

作用于实例方法,当前实例加锁,进入同步代码前要获得当前实例的锁;

作用于代码块,对括号里配置的对象加锁。

作用域静态方法,当前类加锁,进去同步代码前要获得当前类对象的锁;

从字节码角度分析synchronized实现

javap -c ***.class文件反编译

synchronized同步代码块

javap -c .\LockSyncDemo.class(文件反编译)

synchronized同步代码块:实现使用的是monitorenter和monitorexit指令

synchronized普通同步方法

synchronized普通同步方法:调用指令将会检查方法的ACC_SYNCHRONIZED访问标志是否被设置。如果设置了,执行线程会将先持有monitor锁,然后再执行方法,最后在方法完成(无论是正常完成还是非正常完成)时释放monitor

synchronized静态同步方法

ACC_STATIC,ACC_SYNCHRONIZED访问标志区分该方法是否静态同步方法

2、(代码)locks目录下:LockSyncDemo.java

package com.nanjing.juc.locks;/*** 锁同步演示** @author xizheng* @date 2023-08-14 16:45:14*/
public class LockSyncDemo {Object object = new Object();/*** monitorenter代表锁监视器获得了并进入** 正常执行完毕以后会有* monitorexit说明要退出* synchronized的底层是依赖monitorenter和monitorexit来保证锁的获取和释放*/public void m1(){synchronized (object){//也就是说这行代码,只要哪一个线程持有这把锁了,谁持有谁进来,进来以后干活,用完以后再将其释放System.out.println("----hello synchronized code block");//throw new RuntimeException("------exp");}}public synchronized void m2(){System.out.println("----hello synchronized m2");}public static synchronized void m3(){System.out.println("----hello static synchronized m3");}public static void main(String[] args) {}
}

三十四、多线程锁之synchronized底层原语分析

反编译synchronized锁的是什么

面试题:为什么任何一个对象都可以成为一个锁

什么是管程monitor

大厂面试题讲解

【Java集合类】

1、从集合开始吧,介绍一下常用的集合类,哪些是有序的,哪些是无序的

2、hashmap是如何寻址的,哈希碰撞后是如何存储数据的,1.8后什么时候变成红黑树、说下红黑树,红黑树有什么好处

3、concurrenthashmap怎么实现线程安全,一个里面会有几个段segment,jdk1.8后有优化concurrenthashmap吗?分段锁有什么坏处

【多线程JUC】

4、reentrantlock实现原理,简单说下aqs

5、synchronized实现原理,monitor对象什么时候生成的?知道mnitor的monitorenter和monitorexit这两个是怎么保证同步的吗?或者说,这两个操作计算机底层是如何执行的

6、刚刚你提到了synchronized的优化过程,详细说明一下吧。偏向锁和轻量级锁有什么区别?

7、线程池几个参数说下,你们项目中如何根据实际场景设置参数的,为什么cpu密集设置的线程数集型少

什么是管程monitor

在HotSpot虚拟机中,monitor采用ObjectMonitor实现

上述C++源码解读

ObjectMonitor.java->ObjectMonitor.cpp->objectMonitor.hpp

objectMonitor.hpp

每个对象天生都带着一个对象监视器

每一个被锁住的对象都会和Monitor关联起来

提前剧透,混个眼熟

synchronized必须作用域某个对象中,所以Java在对象的头文件存储了锁的相关信息。锁升级功能主要依赖于MarkWord中的锁标志位和释放偏向锁标志位,后续讲解解锁升级时候我们再加深,目前为了承前启后的学习,对下图先混个眼熟即可

Hotspot的实现

三十五、多线程之公平锁和非公平锁

从ReentrantLock卖票demo演示公平锁和非公平现象

公平锁是指多个线程按照申请锁的顺序来获取锁,这里类似排队买票,先来的人先买后来的人在队尾排着,这是公平的 Lock lock = new ReentrantLock(true);//true 表示公平锁,先来先得
非公平锁

是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁,在高并发环境下,有可能造成优先级翻转或者饥饿的状态(某个线程一致得不到锁)

Lock lock = new ReentrantLock(false);//false 表示非公平锁,后来的也可能先获得锁

Lock lock = new ReentrantLock();//默认非公平锁

为什么会有公平锁和非公平锁的设计?为什么默认非公平?

1 恢复挂起的线程到真正锁的获取还是有时间差的,从开发人员来看这个时间微乎其微,但是从CPU的角度来看,这个时间差存在的还是很明显的,所以非公平锁能更充分的利用CPU的时间片,尽量减少CPU空闲状态时间。

2 使用多线程很重要的考量点是线程切换的开销,当采用非公平锁时,当1个线程请求锁获取同步状态,然后释放同步状态,所以刚释放锁的线程在此刻再次获取同步状态的概率就变得非常大,所以就减少了线程的开销。

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

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

相关文章

Java中创建List接口、ArrayList类和LinkedList类的常用方法(一)

List接口 要了解List接口,就不得不说起Java的集合框架。 (该图来自菜鸟教程) Collection接口和Map接口 Java 集合框架主要包括两种类型的容器,集合Collection和图Map。 Collection接口代表了单列集合,它包含了一组…

微信公众号怎么申请超过2个

一般可以申请多少个公众号?目前公众号申请数量的规定是从2018年底开始实施的,至今没有变化。规定如下:1、个人可以申请1个个人主体的公众号;2、企业(有限公司)可以申请2个公众号;3、个体户可以申…

MyBatis 的XML实现方法(JAVA)

数据库表的结构如下: DROP DATABASE IF EXISTS test; CREATE DATABASE test DEFAULT CHARACTER SET utf8mb4; -- 使⽤数据数据 USE test; -- 创建表[⽤⼾表] DROP TABLE IF EXISTS userinfo; CREATE TABLE userinfo ( id INT ( 11 ) NOT NULL AUTO_INCREMENT, user…

如何本地搭建Splunk Enterprise数据平台并实现任意浏览器公网访问

文章目录 前言1. 搭建Splunk Enterprise2. windows 安装 cpolar3. 创建Splunk Enterprise公网访问地址4. 远程访问Splunk Enterprise服务5. 固定远程地址 前言 本文主要介绍如何简单几步,结合cpolar内网穿透工具实现随时随地在任意浏览器,远程访问在本地…

MacM1Pro Parallels19.1.0 CentOS7.9 Install PostgrepSQL

相关阅读 MacM1Pro安装 Parallels Desktop 19.1.0 https://blog.csdn.net/qq_41594280/article/details/135420241 MacM1Pro Parallels安装Parallels Tools https://blog.csdn.net/qq_41594280/article/details/135398780 MacM1Pro Parallels安装CentOS7.9 https://blog.csdn.n…

win7或win10如何设置休眠不断网

win7电脑一断休眠wifi网络就会断,那么怎么办呢?该如何设置Win7电脑休眠时不断开WiFi呢?怎么办呢?下面为大家介绍一下方法能使大脑休眠时不断开WiFi网络。 设置Win7电脑休眠时不断开WiFi教程如下: 1、首先点击桌面右下角的.无线图标&#xf…

[嵌入式软件][启蒙篇][仿真平台] STM32F103实现串口输出输入、ADC采集

上一篇:[嵌入式软件][启蒙篇][仿真平台] STM32F103实现LED、按键 文章目录 一、串口输出(1) 简介(2) 示例代码(3) 仿真效果 二、串口输入(1) 简介(2) 示例代码(3) 仿真效果 三、ADC采集(1) 简介(2) 示例代码(电压)(3) 仿真效果 (…

Conda python管理环境environments 一 从入门到精通

Conda系列: 翻译: Anaconda 与 miniconda的区别Miniconda介绍以及安装Conda python运行的包和环境管理 入门 使用 conda,可以创建、导出、列出、删除和更新 具有不同 Python 版本和/或 安装在其中的软件包。在两者之间切换或移动 环境称为激活环境。您…

vue中的插槽

在vue中&#xff0c;有的名词听着高大上&#xff0c;挺怪异的&#xff0c;比如插槽&#xff0c;就是slot&#xff0c;它的作用是为了解决组件之间写的内容在组件中的使用问题。 一、插槽的作用 <!DOCTYPE html> <html> <head><title>Vue中的插槽</…

接口测试-Mock测试方法

一、关于Mock测试 1、什么是Mock测试&#xff1f; Mock 测试就是在测试过程中&#xff0c;对于某些不容易构造&#xff08;如 HttpServletRequest 必须在Servlet 容器中才能构造出来&#xff09;或者不容易获取的比较复杂的对象&#xff08;如 JDBC 中的ResultSet 对象&#…

EHS管理系统为何需要物联网的加持?

EHS是Environment、Health、Safety的缩写&#xff0c;是从欧美企业引进的管理体系&#xff0c;在国外也被称为HSE。EHS是指健康、安全与环境一体化的管理。 而在国内&#xff0c;整个EHS市场一共被分成三类&#xff1b; 一类是EHS管培体系&#xff0c;由专门的EHS机构去为公司…

有色金属市场分析:预计2023年产量增幅在3.5%左右

上周各有色金属品种走势接近&#xff0c;均呈现出周初持续走弱、最后两个交易日反弹的走势。影响有色金属行情的主线逻辑一个是美国债务上限谈判的进展情况&#xff0c;另一个是全球经济衰退的预期。上周四和上周五市场整体反弹&#xff0c;主要由于美国债务上限谈判出现进展&a…

day27 组合总和 组合总和Ⅱ 分割回文串

题目1&#xff1a;39 组合总和 题目链接&#xff1a;39 组合总和 题意 找出无重复元素的正整数数组candidates中元素和为目标数target的所有不同组合&#xff0c;同一个数字可重复选取 回溯 回溯三部曲&#xff1a; 1&#xff09;参数和返回值 2&#xff09;终止条件 3…

php基础学习之常量

php常量的基本概念 常量是在程序运行中的一种不可改变的量&#xff08;数据&#xff09;&#xff0c;常量一旦定义&#xff0c;通常不可改变&#xff08;用户级别&#xff09;。 php常量的定义形式 使用define函数&#xff1a;define("常量名字", 常量值);使用cons…

EasyDarwin计划新增将各种流协议(RTSP、RTMP、HTTP、TCP、UDP)、文件转推RTMP到其他视频直播平台,支持转码H.264、文件直播推送

之前我们尝试做过EasyRTSPLive&#xff08;将RTSP流转推RTMP&#xff09;和EasyRTMPLive&#xff08;将各种RTSP/RTMP/HTTP/UDP流转推RTMP&#xff0c;这两个服务在市场上都得到了比较多的好评&#xff0c;其中&#xff1a; 1、EasyRTSPLive用的是EasyRTSPClient取流&#xff…

内网穿透的应用-如何使用Docker部署Redis数据库并结合内网穿透工具实现公网远程访问

文章目录 前言1. 安装Docker步骤2. 使用docker拉取redis镜像3. 启动redis容器4. 本地连接测试4.1 安装redis图形化界面工具4.2 使用RDM连接测试 5. 公网远程访问本地redis5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定TCP地址远程访问 前言 本文主要介绍如何在Ub…

RT-Thread 17. 中断发送信号量后线程去处理信号量

1. 代码 //sem.c #include <rtthread.h> #include <rtdevice.h> #include "drv_gpio.h"#define THREAD_PRIORITY 25 #define THREAD_TIMESLICE 5#define LED3_PIN GET_PIN(B, 3) ALIGN(RT_ALIGN_SIZE) static char thread3_stack[1024]; static struct…

【Spring 篇】MyBatis多表操作:编织数据的交响乐

欢迎来到MyBatis的多表操作世界&#xff01;在这个充满交响乐的舞台上&#xff0c;我们将探索如何巧妙地编织多个数据表的数据&#xff0c;创造出一场旋律动听的数据交响曲。无需繁琐的SQL拼接&#xff0c;MyBatis让多表操作变得优雅而简单。让我们一起进入这个音乐殿堂&#x…

司铭宇老师:房地产电话营销培训:房地产电话销售话术与销售技巧:打造高转化率的电话营销策略

房地产电话营销培训&#xff1a;房地产电话销售话术与销售技巧&#xff1a;打造高转化率的电话营销策略 在房地产销售中&#xff0c;电话销售是一种常见且有效的营销手段。它不仅可以快速触达潜在客户&#xff0c;还能够建立起销售人员与客户之间的初步信任关系。然而&#xff…

大模型学习之书生·浦语大模型6——基于OpenCompass大模型评测

基于OpenCompass大模型评测 关于评测的三个问题Why/What/How Why What 有许多任务评测&#xff0c;包括垂直领域 How 包含客观评测和主观评测&#xff0c;其中主观评测分人工和模型来评估。 提示词工程 主流评测框架 OpenCompass 能力框架 模型层能力层方法层工具层 支持丰富…