Java多线程高并发专题——常见面试题

本文深入探讨了Java多线程中的关键概念,包括双重检查锁定(DCL)、volatile关键字的作用以及如何避免指令重排序带来的问题。文章还讲解了死锁的四个必要条件,线程生命周期的五个阶段,并对比了悲观锁与乐观锁的优缺点。此外,还讨论了线程池的使用、异常处理以及线程同步的最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

			1DCL

1)DCL的全称:双重检查加锁(double-checked locking),DCL是在单例模式下的懒汉式写法,这样可以比较高效的处理线程安全问题,但是在DCL双重锁下依然会运行出可能出现的线程安全问题,这就是指令重排序的问题,所以我们就会用到volatile关键字,等会我会在第二点介绍这个关键字,首先来看看懒汉式双重锁的写法:
请添加图片描述
可见在懒汉式的注释下便是双重锁的写法,但是我们也看到了定义空对象时用到的volatile关键字。

			2volatile关键字

2)volatile关键字的两层语义
  一旦一个共享变量(类的成员变量)被volatile修饰之后,那么就具备了两层语义:
  一、保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
  二、禁止进行指令重排序。
  下面来看两段代码:
  //线程1
boolean stop = false;
while(!stop){
doSomething();
}
//线程2
stop = true;
解释:
这段代码是很典型的一段代码,很多人在中断线程时可能都会采用这种标记办法。但是事实上,这段代码会完全运行正确么?即一定会将线程中断么?不一定,也许在大多数时候,这个代码能够把线程中断,但是也有可能会导致无法中断线程(虽然这个可能性很小,但是只要一旦发生这种情况就会造成死循环了)。
  下面解释一下这段代码为何有可能导致无法中断线程。在前面已经解释过,每个线程在运行过程中都有自己的工作内存,那么线程1在运行的时候,会将stop变量的值拷贝一份放在自己的工作内存当中。
  那么当线程2更改了stop变量的值之后,但是还没来得及写入主存当中,线程2转去做其他事情了,那么线程1由于不知道线程2对stop变量的更改,因此还会一直循环下去。
  但是用volatile修饰之后就变得不一样了:
  第一:使用volatile关键字会强制将修改的值立即写入主存;
  第二:使用volatile关键字的话,当线程2进行修改时,会导致线程1的工作内存中缓存变量stop的缓存行无效(反映到硬件层的话,就是CPU的L1或者L2缓存中对应的缓存行无效);
  第三:由于线程1的工作内存中缓存变量stop的缓存行无效,所以线程1再次读取变量stop的值时会去主存读取。
  那么在线程2修改stop值时(当然这里包括2个操作,修改线程2工作内存中的值,然后将修改后的值写入内存),会使得线程1的工作内存中缓存变量stop的缓存行无效,然后线程1读取时,发现自己的缓存行无效,它会等待缓存行对应的主存地址被更新之后,然后去对应的主存读取最新的值。
  那么线程1读取到的就是最新的正确的值。

其次:
在前面提到volatile关键字能禁止指令重排序,所以volatile能在一定程度上保证有序性。
  volatile关键字禁止指令重排序有两层意思:
  一、当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行;
  二、在进行指令优化时,不能将在对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行。
//x、y为非volatile变量
//flag为volatile变量
x = 2; //语句1
y = 0; //语句2
flag = true; //语句3
x = 4; //语句4
y = -1; //语句5
由于flag变量为volatile变量,那么在进行指令重排序的过程的时候,不会将语句3放到语句1、语句2前面,也不会讲语句3放到语句4、语句5后面。但是要注意语句1和语句2的顺序、语句4和语句5的顺序是不作任何保证的。
  并且volatile关键字能保证,执行到语句3时,语句1和语句2必定是执行完毕了的,且语句1和语句2的执行结果对语句3、语句4、语句5是可见的。
  
3死锁
3)死锁的四个必要条件:
一、 互斥
二、请求保持
三、环路等待
四、不可剥夺条件
有其中一个条件都有可能造成死锁,具体来详细介绍:
第一点互斥
这点根据字面意思很好理解,互斥就是两者互相排斥,互不想让,就好比两个人过独木桥,双方都不愿意让对方,从而导致两者都难以通过独木桥,我们的程序也是如此的,如果两个程序双方都不愿意退让一步,都卡在一个位置上就会造成死锁,从而大量的占据CPU,而什么事也没干。
第二点请求保持:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值