“一身孤勇,无畏颠沛过万里;一寸赤心,奔赴理想写真义”
目录
synchronized和ReetrantLock有什么区别?
synchronized和volatile有什么区别?
谈谈对volatile的理解?
谈谈对synchronized的理解?
CAS和synchronized的使用场景?
谈谈对原子类的理解?
Atomic原理是什么?
谈谈对ThreadLocal的理解?
JDBC连接数据库的步骤是什么?
话不多说,发车!
synchronized和ReetrantLock有什么区别?
- synchronized是关键字,ReetrantLock是类,这是二者的本质区别
- synchronized依赖于JVM,所以所做的优化是在虚拟机层面,并没有直接暴露给我们;ReentrantLock依赖于API,可以通过阅读代码来看它是如何实现的
synchronized和volatile有什么区别?
- volatile告诉JVM当前变量在本地内存中的值是不确定的,需要到主存中去读取;synchronized则是锁定当前变量,只有当前线程可以访问,其他线程被阻塞
- volatile只可以用在变量;synchronized可以用在变量、方法、类上
- volatile不会造成线程的阻塞;synchronized会造成线程的阻塞
- volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化
谈谈对volatile的理解?
- volatile读的内存语义是:当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效,线程接下来需要到主内存中读取变量;volatile写的内存语义是JMM会把该线程对应的本地内存中的共享变量刷新到主内存
- 被volatile修饰的变量有两个特点:保证了不同线程对该变量操作的可见性;禁止编译器对其进行重排序
谈谈对synchronized的理解?
- 解决的是多个线程之间访问资源的同步性,它可以保证被它修饰的方法或代码块在任意时刻只能有一个线程执行
- 早期版本中,synchronized属于重量级锁,如果要挂起或者阻塞某一个进程都需要操作系统帮忙完成,而操作系统实现线程中的切换需要从用户态切换到内核态,这个状态切换耗时比较长,所以早期synchronized效率比较低;而后期JVM对其做了大量的优化,引入了偏向锁、轻量级锁、自旋锁、锁消除
- synchronized同步代码块的实现使用的是monitorenter 和monitorexit 指令,monitorenter 指向同步代码块的开始位置,monitorexit 指向同步代码块的结束位置;当执行 monitorenter 指令时,线程试图获取锁,当计数器为 0 则可以成功获取,获取后将锁计数器设为 1 ;相应的在执行monitorexit 指令后,将锁计数器设为 0,表明锁被释放。如果获取对象锁失败,那当前线程就要阻塞等待,直到锁被另外一个线程释放为止。
CAS和synchronized的使用场景?
- 对于资源竞争少的情况,使用synchronized开销比较大,因为涉及到内核态和用户态之间的转换;而CAS基于硬件实现,不需要进入内核,且自旋的概率比较低,所以开销比较少
- 对于资源竞争多的情况,CAS自旋的概率比较高,开销会比较大,效率不如synchronized
谈谈对原子类的理解?
- 原子类就是具有原子操作特征的类,在多个线程一起执行的时候,一个操作一旦开始就不会被其他线程所干扰
- Atomic包中的原子类可以分为四类:基本类型原子类、数组类型原子类、引用类型原子类、原子更新属性
Atomic原理是什么?
- 在多线程的环境下,当有多个线程对单个变量进行操作时,具有排他性,即当多个线程同时对该变量的值进行更新时,只有一个线程能操作成功,未成功的线程会继续尝试,直到成功为止
谈谈对ThreadLocal的理解?
- ThreadLocal是线程变量,ThreadLocal中所填充的变量只属于当前线程,对其他线程而言是隔离的,ThreadLocal为变量在每个线程中都创建了一个变量副本,每个线程可访问自己内部的变量副本
- get():用来获取在当前线程中保存的变量副本
- set():用来设置当前线程中的变量副本
- remove():用来移除当前线程的变量副本
JDBC连接数据库的步骤是什么?
- 加载JDBC驱动程序:Class.forName("com.mysql.jdbc.Driver")
- 提供URL:例如jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gbk ;
- 创建数据库的连接,获取Connection对象:
- Connection connection =DriverManager.getConnection(url, user, pwd);
- 创建一个statement:Statement statement = connection.createStatement();
- 定义SQL语句,执行SQL语句:ResultSet resultSet = statement.executeQuery(sql);
- 关闭连接:resultSet.close();statement.close();connection.close();
整理面经不易,觉得有帮助的小伙伴点个赞吧~感谢收看!