![](https://img-blog.csdnimg.cn/20190918140053667.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
多线程面试题
多线程面试题
Mr.Aholic
全栈开发工程师 主java后端。喜欢旅游,已经旅游的城市地点:河南老家、广州、佛山、深圳、上海、山西、长沙、张家界、武汉、新疆-乌鲁木齐、新疆-吐鲁番、云南-昆明,郑州等。备考明年的 高级系统分析师 和 系统架构师【2022届毕业生---软件工程专业】
展开
-
【多线程面试题二十五】、说说你对AQS的理解
Semaphore用它来表示剩余的许可数量,当许可数量为0时,对未获取到许可但正在努力尝试获取许可的线程来说,会进入同步等待队列,阻塞,直到一些线程释放掉持有的许可(state+1),然后争用释放掉的许可。ReentrantLock用它来表示锁的持有者线程已经重复获取该锁的次数,而对于非锁的持有者线程来说,如果state大于0,意味着无法获取该锁,将该线程包装为Node,加入到同步等待队列里。AQS采用模板方法模式,在内部维护了n多的模板的方法的基础上,子类只需要实现特定的几个方法(不是抽象方法!原创 2023-11-15 12:36:14 · 148 阅读 · 0 评论 -
【多线程面试题二十四】、 说说你对JUC的了解
JUC是java.util.concurrent的缩写,该包参考自EDU.oswego.cs.dl.util.concurrent,是JSR 166标准规范的一个实现。JSR 166是一个关于Java并发编程的规范提案,在JDK中该规范由java.util.concurrent包实现。即JUC是Java提供的并发包,其中包含了一些并发编程用到的基础组件。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。原创 2023-11-08 08:28:20 · 86 阅读 · 0 评论 -
【多线程面试题二十三】、 说说你对读写锁的了解volatile关键字有什么用?
注意,虽然volatile能够保证可见性,但它不能保证原子性。volatile变量在各个线程的工作内存中是不存在一致性问题的,但是Java里面的运算操作符并非原子操作,这导致volatile变量的运算在并发下一样是不安全的。当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见,在其后面的操作肯定还没有进行;在进行指令优化时,不能将对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行。原创 2023-11-08 08:23:19 · 60 阅读 · 0 评论 -
【多线程面试题二十二】、 说说你对读写锁的了解
与传统锁不同的是读写锁的规则是可以共享读,但只能一个写,总结起来为:读读不互斥、读写互斥、写写互斥,而一般的独占锁是:读读互斥、读写互斥、写写互斥,而场景中往往读远远大于写,读写锁就是为了这种优化而创建出来的一种机制。因此当并发不是很高的情况下,读写锁由于需要额外维护读锁的状态,可能还不如独占锁的效率高。3、可降级:写线程获取写锁之后,其还可以再次获取读锁,然后释放掉写锁,那么此时该线程是读锁状态,也就是降级操作。2、可重入:读线程获取读锁之后可以再次获取读锁,写线程获取写锁之后可以再次获取写锁。原创 2023-11-02 23:36:08 · 107 阅读 · 0 评论 -
【多线程面试题二十一】、 分段锁是怎么实现的?
其实说的简单一点就是:容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。在锁上发生竞争时将通水导致这两种问题,使用独占锁时保护受限资源的时候,基本上是采用串行方式—-每次只能有一个线程能访问它。2、降低锁的请求频率;原创 2023-11-02 23:33:23 · 142 阅读 · 0 评论 -
【多线程面试题二十】、 如何实现互斥锁(mutex)?
自JDK 5起,Java类库中新提供了java.util.concurrent包(J.U.C包),其中的java.util.concurrent.locks.Lock接口便成了Java的另一种全新的互斥同步手段。基于Lock接口,用户能够以非块结构(Non-Block Structured)来实现互斥同步,从而摆脱了语言特性的束缚,改为在类库层面去实现同步,这也为日后扩展出不同调度算法、不同特征、不同性能、不同语义的各种锁提供了广阔的空间。踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。原创 2023-10-30 19:58:37 · 477 阅读 · 0 评论 -
【多线程面试题十九】、 公平锁与非公平锁是怎么实现的?
公平锁和非公平锁在说的获取上都使用到了 volatile 关键字修饰的state字段, 这是保证多线程环境下锁的获取与否的核心。在Java中实现锁的方式有两种,一种是使用Java自带的关键字synchronized对相应的类或者方法以及代码块进行加锁,另一种是ReentrantLock,前者只能是非公平锁,而后者是默认非公平但可实现公平的一把锁。与公平锁的区别在于新晋获取锁的进程会有多次机会去抢占锁,被加入了等待队列后则跟公平锁没有区别。tryAcquire 是一个抽象方法,是公平与非公平的实现原理所在。原创 2023-10-30 19:57:00 · 232 阅读 · 1 评论 -
【多线程面试题十八】、说一说Java中乐观锁和悲观锁的区别
乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。在JDK1.5 中新增 java.util.concurrent (J.U.C)就是建立在CAS之上的。相对于对于 synchronized 这种阻塞算法,CAS是非阻塞算法的一种常见实现。所以J.U.C在性能上有了很大的提升。悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。原创 2023-10-30 19:53:22 · 362 阅读 · 0 评论 -
【多线程面试题十七】、如果不使用synchronized和Lock,如何保证线程安全?
主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。原创 2023-10-30 19:52:28 · 179 阅读 · 1 评论 -
【多线程面试题十六】、谈谈ReentrantLock的实现原理
其中同步队列是一个双向链表,里面储存的是处于等待状态的线程,正在排队等待唤醒去获取锁,而条件队列是一个单向链表,里面储存的也是处于等待状态的线程,只不过这些线程唤醒的结果是加入到了同步队列的队尾,AQS所做的就是管理这两个队列里面线程之间的等待状态-唤醒的工作。通过Sync重写的方法tryAcquire、tryRelease可以知道,ReentrantLock实现的是AQS的独占模式,也就是独占锁,这个锁是悲观锁。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。利己利人、所谓双赢。原创 2023-10-30 19:51:14 · 174 阅读 · 0 评论 -
【多线程面试题十五】、synchronized可以修饰静态方法和静态代码块吗?
主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。当修饰静态方法时,监视器锁(monitor)便是对象的Class实例,因为Class数据存在于永久代,因此静态方法锁相当于该类的一个全局锁。synchronized可以修饰静态方法,但不能修饰静态代码块。原创 2023-10-30 19:48:45 · 500 阅读 · 0 评论 -
【多线程面试题十四】、说一说synchronized的底层实现原理
如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象。原创 2023-10-30 19:47:46 · 281 阅读 · 0 评论 -
【多线程面试题十三】、说一说synchronized与Lock的区别
主要分享开发知识、学习资料、毕业设计指导等。6、synchronized锁可重入、不可中断、非公平;Lock锁可重入、可中断、可公平/不公平,并可以细分读写锁以提高效率。3、synchronized在代码执行完或出现异常时自动释放锁;Lock不会自动释放锁,需要在finally中显示释放锁。1、synchronized是Java关键字,在JVM层面实现加锁和解锁;Lock是一个接口,在代码层面实现加锁和解锁。Lock可以设置获取锁失败的超时时间。2、synchronized可以用在代码块上、方法上;原创 2023-10-29 19:58:55 · 104 阅读 · 0 评论 -
【多线程面试题十二】、阻塞线程的方式有哪些?
主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。程序调用了线程的suspend()方法将该线程挂起,但这个方法容易导致死锁,所以应该尽量避免使用该方法。线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞;线程试图获得一个同步监视器,但该同步监视器正被其他线程所持有;线程调用sleep()方法主动放弃所占用的处理器资源;线程在等待某个通知(notify);原创 2023-10-29 19:57:13 · 98 阅读 · 0 评论 -
【多线程面试题十一】、如何实现子线程先执行,主线程再执行?
Thread类提供了让一个线程等待另一个线程完成的方法——join()方法。当在某个程序执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加入的join线程执行完为止。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。join()方法通常由使用线程的程序调用,以将大问题划分成许多小问题,每个小问题分配一个线程。当所有的小问题都得到处理后,再调用主线程来进一步操作。启动子线程后,立即调用该线程的join()方法,则主线程必须等待子线程执行完成后再执行。原创 2023-10-29 19:55:26 · 137 阅读 · 0 评论 -
【多线程面试题十】、说一说notify()、notifyAll()的区别
主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。原创 2023-10-29 19:52:06 · 77 阅读 · 0 评论 -
【多线程面试题九】、说一说sleep()和wait()的区别
主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。3、sleep()不会释放锁,而wait()会释放锁,并需要通过notify()/notifyAll()重新获取锁。1、sleep()是Thread类中的静态方法,而wait()是Object类中的成员方法;2、sleep()可以在任何地方使用,而wait()只能在同步方法或同步代码块中使用;原创 2023-10-29 19:49:02 · 60 阅读 · 0 评论 -
【多线程面试题 八】、说一说Java同步机制中的wait和notify
wait()、notify()、notifyAll()用来实现线程之间的通信,这三个方法都不是Thread类中所声明的方法,而是Object类中声明的方法。notify()方法用于唤醒一个正在等待相应对象锁的线程,使其进入就绪队列,以便在当前线程释放锁后竞争锁,进而得到CPU的执行。notifyAll()方法用于唤醒所有正在等待相应对象锁的线程,使它们进入就绪队列,以便在当前线程释放锁后竞争锁,进而得到CPU的执行。就绪队列存储了已就绪(将要竞争锁)的线程,阻塞队列存储了被阻塞的线程。利己利人、所谓双赢。原创 2023-10-29 19:43:39 · 181 阅读 · 0 评论 -
【多线程面试题 七】、 说一说Java多线程之间的通信方式
必须要注意的是,Condition 的 await()/signal()/signalAll() 使用都必须在lock保护之内,也就是说,必须在lock.lock()和lock.unlock之间才可以使用。即:Conditon中的await()对应Object的wait(),Condition中的signal()对应Object的notify(),Condition中的signalAll()对应Object的notifyAll()。反之,当一个线程被wait后,就会进入阻塞队列,等待被唤醒。原创 2023-10-29 19:42:12 · 95 阅读 · 0 评论 -
【多线程面试题 六】、 如何实现线程同步?
主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。原创 2023-10-28 22:00:22 · 318 阅读 · 0 评论 -
【多线程面试题 五】、 介绍一下线程的生命周期
当一个线程开始运行后,它不可能一直处于运行状态,线程在运行过程中需要被中断,目的是使其他线程获得执行的机会,线程调度的细节取决于底层平台所采用的策略。如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态,如果计算机只有一个CPU,那么在任何时刻只有一个线程处于运行状态。当线程对象调用了start()方法之后,该线程处于就绪状态,Java虚拟机会为其创建方法调用栈和程序计数器,处于这个状态中的线程并没有开始运行,只是表示该线程可以运行了。有兴趣的可以关注一下。原创 2023-10-28 21:58:54 · 40 阅读 · 0 评论 -
【多线程面试题 四】、 线程是否可以重复启动,会有什么后果?
当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时它和其他的Java对象一样,仅仅由Java虚拟机为其分配内存,并初始化其成员变量的值。此时的线程对象没有表现出任何线程的动态特征,程序也不会执行线程的线程执行体。当线程对象调用了start()方法之后,该线程处于就绪状态,Java虚拟机会为其创建方法调用栈和程序计数器,处于这个状态中的线程并没有开始运行,只是表示该线程可以运行了。至于该线程何时开始运行,取决于JVM里线程调度器的调度。主要分享开发知识、学习资料、毕业设计指导等。原创 2023-10-28 21:56:02 · 115 阅读 · 0 评论 -
【多线程面试题 三】、 run()和start()有什么区别?
调用start()方法启动线程时,系统会把该run()方法当成线程执行体来处理。但如果直接调用线程对象的run()方法,则run()方法立即就会被执行,而且在run()方法返回之前其他线程无法并发执行。也就是说,如果直接调用线程对象的run()方法,系统把线程对象当成一个普通对象,而run()方法也是一个普通方法,而不是线程执行体。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。run()方法被称为线程执行体,它的方法体代表了线程需要完成的任务,而start()方法用来启动线程。原创 2023-10-28 21:54:41 · 77 阅读 · 0 评论 -
【多线程面试题 二】、 说说Thread类的常用方法
setDaemon(boolean on):将该线程标记为守护线程或用户线程,如果不标记默认是非守护线程;yield():使当前执行的线程自愿暂时放弃对处理器的使用权并允许其他线程执行;interrupted():返回当前执行的线程是否已经被中断;setName(String name):设置该线程的名字;getPriority():返回该线程的优先级;isDaemon():返回该线程是否是守护线程;getName():返回该线程的名字;getId():返回该线程的id;join():等待该线程终止;原创 2023-10-28 21:53:23 · 39 阅读 · 0 评论 -
【多线程面试题 一】、 创建线程有哪几种方式?
通过继承Thread类、实现Runnable接口、实现Callable接口都可以实现多线程,不过实现Runnable接口与实现Callable接口的方式基本相同,只是Callable接口里定义的方法有返回值,可以声明抛出异常而已。1、创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call()方法有返回值。然后再创建Callable实现类的实例。1、定义Runnable接口的实现类,并实现该接口的run()方法,该run()方法将作为线程执行体。原创 2023-10-28 21:50:27 · 97 阅读 · 0 评论