文章目录
前言
又是一年春招季,距离自己第一次在网上找Java开发的工作差不多过去一年了,这一年有大半年是在外面实习,从最开始疯狂背面经到后来在工作中慢慢理解这些概念,然后最后在实际开发中使用到具体的知识,这相当于是一个质的跃迁。
最近又在开始复习八股文和整理自己的实习经验这些,今天刚好是我们学校这个区的招聘会,看那待遇真的让人心寒,在这互联网的环境也不太好,就越发得觉得这些努力没有白费,如果很早之前就松懈了,那我也可能就只能写出这样的简历,找到这样的工作,现在在外面有实际的实习经验,相对于来说面试的时候有更多的话和面试官说了,希望不仅仅是你问我答的那种面试,更希望是一种可以切磋技术并且在工作规划人生看法能让我有不同看法或者听到不同见解的。
能坚持到现在我觉得大家首先都是优秀的,其次就是都喜欢编程的,我是在编程的时候真的会有一种很舒服的感觉,那时一心只想完成需求,那段时间总过得很快,很喜欢完成需求后获得的那种成就感,是觉得自己是真的在干一些有意义的事情:或者帮助了业务,减少重复性工作,提升了效率。
这次春招是在两三段实习后,毕设和健身间隙准备的,在大学的最后一期,在这自习室送走了22届考研,看着23届考研,现在又是一堆陌生的24届考研的同学,随着在校园熟悉的面孔越来越少,说明我们真的要毕业了。
有好长一段时间没有写博客了,这段时间有在好好工作,完成需求;有在好好生活,陪着家人;也在这间隙锻炼了身体,认识了一群相同行业的朋友。
接下来还是不能停下求职的脚步,一边学习新知识,复习总结学过的,争取都能找到一个互相心仪的公司
大厂面试题复盘 —— 并发编程高级面试解析
一、Synchronized相关问题
- Synchronized用过吗,其原理是什么?
- 你刚才提到获取对象的锁,这个"锁"到底是什么?如何确定对象的锁?
- 什么是可重入性,为什么说Synchronized是可重入锁?
- JVM对Java的原生锁做了哪些优化?
- 为什么说Synchronized是非公平锁?
- 什么是锁消除和锁粗化?
- 为什么说Synchronized是一个悲观锁?乐观锁的实现原理又是什么?什么是CAS,他有
- 乐观锁一定就是好的吗?
二、可重入锁ReentrantLock及其他显式锁相关问题
跟Synchronized相比,可重入锁ReentrantLock其实现原理有什么不同?
那么请谈谈AQS框架是怎么回事儿?
请尽可能详尽地对比下Synchronized和ReentrantLock的异同
ReentrantLock是如何实现可重入性的?
你怎么理解Java多线程的?怎么处理并发?线程池有哪几个核心参数?
Java加锁有哪几种锁?
简单说说lock
hashmap的实现原理?hash冲突怎么解决?为什么使用红黑树?
spring里面都使用了哪些设计模式?循环依赖怎么解决?
项目中哪个地方用了countdownlanch,怎么使用的?
从轻松的乐观锁和悲观锁开讲
悲观锁:认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Synchronized关键字和Lock的实现类的都是悲观锁。
适合写操作多的场景,先加速可以保证写操作时数据正确。显示的锁定之后再操作同步资源。一句话:狼性锁
乐观锁:认为自己在使用数据时不会有别的线程修改数据或资源,所以不会添加锁。在Java中是通过使用无锁编程来实现,只是在更新数据的时候去判断,之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果这个数据已经被其他线程更新,则根据不同的实现方式执行不同的操作,比如放弃修改、重试抢锁等等
判断规则
- 版本号机制Version
- 最常采用的是CAS算法,Java原子类中的递增操作就通过CAS自旋实现的
适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升。乐观锁则直接去操作同步资源,是一种无锁算法,得之我幸不得我命,再努力就是
一句话:佛系锁两种实现方式:Version版本号机制;CAS
//伪代码说明 //====悲观锁的调用方式 public synchronized void m1(){ //加锁后的业务逻辑 } //====保证多个线程使用的是同一个Lock对象的前提下 ReentrantLock lock = new ReentrantLock(); public void m2(){ lock.lock(); try{ //操作同步资源 }finally{ lock.unlock(); } } //====乐观锁的调用方式 //保证多个线程使用的是同一个AtomicInteger private AtomicInteger atomicInteger = new AtomicInteger(); atomicInteger.incrementAndGet();
通过8种情况演示锁运行案例,看看我们到底锁的是什么
锁相关的8种案例演示code
class Phone{
//资源类
public static synchronized void sendEmail(){
try{
TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) {
e.printStackTrace(); }
System.out.println("----sendEmail");
}
public synchronized void sendSMS(){
System.out.println("----sendSMS");
}
public void hello(){
System.out.println("----hello");
}
}
/**
* @author William
* @create 2022-07-03 18:34
* 题目:谈谈你对多线程锁的理解,8锁案例说明
* 口诀:线程 操作 资源类
* 8锁案例说明:
* 1. 标准访问有ab两个线程,请问先打印邮件还是短信 邮件
* 2. sendEmail方法中加入暂停3秒钟,请问先打印邮件还是短信 邮件
* 3. 添加一个普通的hello方法,请问先打印邮件还是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
* 也就是说如果一个实例对象的普通同步方法获取锁后,该实例对象的其他普通同步方法必须等待获取锁的方法