JAVA面试题多线程&并发篇(二)

发布时间:2023-08-28 12:00

#JAVA面试题多线程&并发篇(二)


文章目录

  • 前言
  • 一、Java中synchronized 和 ReentrantLock 有什么不同?
  • 二、什么是线程安全?
  • 三、Thread类中的yield方法有什么作用?
  • 四、说一说自己对于 synchronized 关键字的了解。
  • 五、说说自己是怎么使用 synchronized 关键字?
  • 六、volatile关键字的作用?
  • 七、常用的线程池有哪些?
  • 八、简述一下对线程池的理解
  • 总结


前言

到了大三的学期的暑假,即将面临找工作的考验。希望这份面试资料能够帮住大家学到自己的知识盲区。加油,我命由我不由天!!!


一、Java中synchronized 和 ReentrantLock 有什么不同?

**相似点:**这俩种同步方式有很多相似之处,他们都是加锁方式同步,而且都是阻塞式同步,也就是说当如果一个线程获得了对象锁,进入了同步块,其他访问同步块的线程必须在同步块外面等待,而进行线程阻塞和唤醒的代价比较高的。

区别:
这俩种方式最大区别就是对于Synchronized来说,它是java语言的关键字,是原生语法层面的互斥,需要JVM实现。在执行monitorenter指令时,首先要尝试获取对象锁。如果这个对象没被锁定,或者当前线程已经拥有了那个对象锁,把锁的计算器加1,相应的,在执行monitorexit指令时会将锁计算器就减1,当计算器为0时,锁就被释放了。如果获取对象锁失败,那当前线程就要阻塞,直到对象锁被另一个线程释放为止。

二、什么是线程安全?

线程安全就是多线程访问同一段代码,不会产生不确定的结果。
如果你的代码在多线程下执行和单线程下执行永远获得同样的结果,那么你的代码线程就是安全的。

线程安全的几个级别:
1、不可变
像String、Integer、Long这些final类型的类,任何一个线程都改变不了他们的值,要改变除非新创建一个,因此这些不可变对象不需要任何同步手段就可以直接在多线程环境下使用。
2、绝对线程安全
不管运行时环境如何,调用者都不需要额外的同步措施。要做到这一点通常需要付出许多的额外代价,Java中标注自己是线程安全的类,实际上绝大多数都不是线程安全的,不过绝对线程安全的类,Java中也有,比方说CopyOnWriteArrayList、CopyOnWriteArraySet
3、相对线程安全
相对线程安全也就是我们通常意义上所说的线程安全,像Vector这种,add、remove方法都是原子操作,不会被打断,但也仅限于此,如果有个线程在遍历某个Vector、有个线程同时在add这个Vector,99%的情况下都会出现ConcurrentModificationException,也就是fail-fast机制。

三、Thread类中的yield方法有什么作用?

Yield方法可以暂停当前正在执行的线程对象,让其它有相同优先级的线程执行。它是一个静态方法而且只保证当前线程放弃CPU占用而不能保证使其它线程一定能占用CPU,执行yield()的线程有可能在进入到暂停状态后马上又被执行。

四、说一说自己对于 synchronized 关键字的了解。

synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized可以保证被它修饰的方法或者代码块在任意时刻只能 有一个线程执行。

五、说说自己是怎么使用 synchronized 关键字?

修饰实例方法:作用于当前对象实例加锁,进入同步代码前要获得当前对象实例的锁修饰静态方法也就是给当前类加锁,会作用于类的所有对象实例,因为静态成员不属于任何一个实例对象。是类成员( static 表明这是该类的一个静态资源,不管new了多少个对象,只有一份)。所以如果一个线程A调用一个实例对象的非静态 synchronized 方法,而线程B需要调用这个实例对象所属类的静态 synchronized 方法,是允许的,不会发生互斥现象,因为访问静态 synchronized 方法占用的锁是当前类的锁,而访问非静态 synchronized 方法占用的锁是当前实例对象锁。 修饰代码块: 指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。 总结: synchronized 关键字加到 static 静态方法和 synchronized(class)代码块上都是是给 Class 类上锁。synchronized关键字加到实例方法上是给对象实例上锁。尽量不要使用 synchronized(String a) 因为JVM中,字符串常量池具有缓存功能。

六、volatile关键字的作用?

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
1、保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2、禁止进行指令重排序。
3、volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
4、volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。
5、volatile仅能实现变量的修改可见性,并不能保证原子性;synchronized则可以保证变量的修改可见性和原子性。
6、volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。

七、常用的线程池有哪些?

**NewSingleThreadExecutor:**创建一个单线程的线程池,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
**newFixedThreadPool:**创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程到达线程池的最大大小。
**newCachedThreadPool:**创建一个可缓存的线程池,此线程池不会对线程大小作限制,线程池大小完全依赖于操作系统能够创建的最大线程大小。
**newScheduledThreadPool:**创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求。
**newSingleThreadExecutor:**创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。

八、简述一下对线程池的理解

1、降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁的消耗。
2、提高响应速度,当任务到达时,任务可以不需要等到线程创建就能立即执行。
3、提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

总结

线程和并发都是非常关键的知识点。整理不易,欢迎大家一起交流,喜欢的朋友记得关注我点赞哟,感谢支持!将会持续的更新下去,你们的点赞和关注是我继续的动力!!!

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号