【Java面试】Java常见面试题整理(带答案)——多线程 - 知乎

最近正在准备面试,网上查了许多的面试题,但是却都很少有相关答案。因此特意在这里整理一份题型以及我自己填充的部分答案,如果有错误,或者部分我不知道结果的题目,可以请大家私信或评论我调整。同时本内容也会不定期进行更新,为了方便检索,会在前面先写问题和问题序号,下面会再写答案。其他相关内容spring、redis、数据库等稍后会一一进行编写。

侵删。

青藤门下走狗:Java常见面试题整理(带答案)——spring9 赞同 · 0 评论文章

青藤门下走狗:Java常见面试题整理(带答案)——基础篇95 赞同 · 4 评论文章

多线程问题

  1. 如何创建线程
  2. 为什么会存在线程安全
  3. 什么是原子性,什么是可见性
  4. Synchronized可以用在哪些地方,区别是什么
  5. 悲观锁和乐观锁的概念
  6. JDK对锁的优化
  7. ReentrantLock和Synchronized区别
  8. ThreadLocal原理
  9. ThreadLocal缺点

多线程答案

1.如何创建线程

线程可以有三种创建方式:
实现Runnable接口,重写里面的run()方法
继承Thread类,重写里面的Run()方法
实现Call接口,重写里面的call()方法。

2.为什么会存在线程安全

多个线程对同一个公共资源的资源竞争。

3.什么是原子性,什么是可见性

原子性:操作是不可中断的,要么全部成功,要么全部失败。
可见性:一个线程修改了共享变量,其他的线程能马上得到通知。

4.Synchronized有几种使用方式,区别是什么

可以使用在方法上和使用在代码块上。
区别:同步方法一次只能有一个线程访问该方法,而在方法中使用同步代码块,可以一次有多个线程访问同一个方法,只不过在访问同步代码块的时候一次只能由一个线程访问。

5.悲观锁和乐观锁的概念

乐观锁:乐观地认为所有的并发操作都是线程安全的,不需要加锁来处理。但为了保证数据没有被修改,会通过CAS操作来进行判定和替换。
悲观锁:悲观地认为所有的并发操作都是线程不安全的,都需要加锁来保证线程安全。

6.JDK对锁的优化

JKD1.6之后增加了锁粗化、锁消除、偏向锁、轻量级锁、重量级锁来对锁进行一个优化。
锁粗化:对一系列的加锁操作,如果是针对同一个资源的锁的获取和释放,可以对这些代码统一放到一个更大的锁范围内。
锁消除:对一些列不会引发线程安全问题的操作进行加锁,JDK会自动取消加锁和释放锁。
偏向锁:这是对Synchronized的优化,从无锁状态到第一次被线程获得锁,会先进入偏向锁状态,如果一直是同一个线程获取锁,则会一直处于偏向锁,直到发生竞争。这只是一个标志,而不是真正的锁。标记中有一个指针指向了当前获取锁的线程的地址,如果地址相同,则判定是同一个线程。如果有其他线程来获取锁,会检查前一个线程是否仍存活(偏向锁不会主动释放),如果存活则膨胀变成轻量级锁。如果不存活,则会从偏向锁变成无锁状态,再由线程去获取锁,如果获取失败,产生了竞争,则也膨胀成轻量级锁。
轻量级锁:这是对Synchronized的优化,从偏向锁的状态发生竞争后,会锁膨胀变成轻量级锁。轻量级锁是在内存有一个锁记录,当某个线程获取到锁后,会将锁记录保存到线程内存中,同时将原本的锁记录指向它的线程内存中的备份锁记录位置。其他线程判断锁记录已经指向了其他线程,因此会进入自旋状态。达到一定的次数或时间后,会膨胀变成重量级锁。
重量级锁:重量级锁是指的监视器锁,这是底层计算机来实现的一个锁,每次的获取和释放,需要消耗大量CPU资源。

7.ReentrantLock和Synchronized区别

(1)ReentrantLock是JDK提供的锁,Synchronized是JVM提供的锁。
(2)R需要编程人员手动进行锁的获取和释放,如果在代码块中出现异常,不会自动释放锁,需要由编程人员在finally中确保释放锁。S则会自动地释放锁。
(3)S是悲观锁和非公平锁和独享锁,而R可以配置公平锁和非公平锁,同时也可以有共享锁和CAS的乐观锁实现。

8.ThreadLocal原理

ThreadLocal采用的是每个线程都复制一份数据的方式来保证数据的安全性。
在ThreadLocal中有一个内部类ThreadLocalMap,以K-V形式来存放数据。同时在Thread类中,有它的一个对象。我们在线程中每次对ThreadLocal赋值,都是先获取当前线程thread,然后将值赋予在thread中的ThreadLocalMap对象中,key是当前的ThreadLocal对象,值是我们需要存储的数据。

9.ThreadLocal缺点

ThreadLocal由于真正存储数据的ThreadLocalMap只单纯地采取了数组的形式来存储数据,因此出现hash冲突时会进行线性寻找位置,会导致大量的hash冲突,造成很高的资源消耗。
同时由于ThreadLocal类是弱引用,可能会存在ThreadLocalMap中的key——ThreadLocal已经被回收了,但是它的Value依然存在,从而导致大量的对象没有办法回收,会出现内存溢出的情况。因此,实际会在操作结束后,对其进行clear,清理key为null的位置。

原网址: 访问
创建于: 2022-10-13 10:30:21
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论