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同步代码块

synchronized普通同步方法

synchronized静态同步方法

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

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

相关文章

【每日一题】670. 最大交换-2024.1.22

题目: 670. 最大交换 给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释: 交换数字2和数字7。示例 2 : 输入: 9973 输出: 9973 解释: 不需要交换。注意: 给定数字的范围是 [0, 1…

【K12】python用科学函数写方程解串联电路问题

物理例题: 代码分析 构造方程: from sympy中导包:Eq(),solve() 列方程函数 Eq()列方程函数 列出I2RP,这里设置P为1 解方程函数 solve((方程1,方程2,方程3),(未知量1&#xff…

【算法】利用模拟算法、规律解算法题(C++)

文章目录 1. 前言2. 算法题1576.替换所有的问号495.提莫攻击6.Z字形变换38.外观数列1419.数青蛙 1. 前言 模拟算法 即模拟问题过程来解决问题的算法。 对于一些算法题,我们只需要将题目的过程 用代码编写出来,再结合其他方法,就可以解决。 …

SpringBoot远程过程调用RPC(WebClient、HTTP Interface客户端)

目录 1. 远程过程调用介绍2. WebClient2.1 pom.xml添加依赖2.2 发送请求的内容2.3 WebClient.builder()2.4 使用示例 3. HTTP Interface3.1 pom.xml添加依赖3.2 使用示例 1. 远程过程调用介绍 以前有sdk(Software Development Kit)工具包,导入jar包,直接…

填空题如何去掉答案?教你3个去除小妙招

填空题如何去掉答案?在日常学习过程中,将写过的试卷填空题去掉答案,是一种非常有效的学习方法,可以帮助学生们更好地巩固和扩充知识点。首先,去掉答案可以让学生们重新审视题目,加深对知识点的理解。其次&a…

如何使用CRM实现销售流程自动化?CRM如何提高销售效率?

科技在当今时代扮演着重要的角色。在商业领域,我们用很多不同的软件来完成业务、提高效率。销售被认为是一个企业的灵魂。没有销售,企业很难生存。为了使销售更加有效,自动化是每个企业都应该采用的一个重要战略。实现销售过程自动化最简单的…

springboot+mysql马拉松赛事志愿者管理系统-计算机毕业设计源码93439

摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对马拉松赛事志愿者管理等问题,对…

Python进阶-Anaconda使用总结

本文是 Anaconda 的使用总结,旨在帮助用户快速搭建 Python 环境、进行数据科学和机器学习工作。首先,介绍了在 Windows 系统上安装 Anaconda 的步骤,包括下载安装程序、配置环境变量以及验证安装。随后,详细列举了 Anaconda 的常用…

【C++干货基地】namespace超越C语言的独特魅力(文末送书)

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引入 哈喽各位铁汁们好啊,我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发,不知道各位的…

【Coding】寒假每日一题Day.5.三国游戏

题目来源 题目来自于AcWing平台:https://www.acwing.com/problem/content/description/4968/。 以blog的形式记录程序设计算法学习的过程,仅做学习记录之用。 题目描述 输入输出格式与数据范围 样例 思路 思路参考自题解:https://www.acwi…

高效构建Java应用:Maven的使用总结

一、Maven简介和快速入门 1.1 Maven介绍 Maven-Introduction Maven 是一款为 Java 项目构建管理、依赖管理的工具(软件),使用 Maven 可以自动化构建、测试、打包和发布项目,大大提高了开发效率和质量。 总结:Maven…

C++入门之基础语法

目录 一.关键字 二.命名空间 2.1命名空间域 2.2展开命名空间域 using namespace bit 使用using将命名空间中的某个成员引入 2.3 头文件#include 2.3.1 头文件的展开和命名空间的展开区别 2.4 C的标准的库命名空间std 2.5 命名空间的套娃 三. C输入输出 3.1 流插入co…