Java多线程之死锁详解
1、死锁
出现场景:当线程A拥有了A对象的锁,想要去获取B对象的锁;线程B拥有了B对象的锁,想要拥有A对象的锁,两个线程在获取锁的时候,都不会释放已经持有的锁,于是,就造成了死锁。
示例代码:
@Slf4j
public class ThreadTest {
private static Object objectA = new Object();
private static Object objectB = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t2 = new Thread(()->{
synchronized (objectA){
log.debug("线程t2获取到了objectA");
synchronized (objectB){
log.debug("线程t2获取到了objectB");
}
}
},"t2");
Thread t1 = new Thread(()->{
synchronized (objectB){
log.debug("线程t1获取到了objectB");
synchronized (objectA){
log.debug("线程t1获取到了objectA");
}
}
},"t1");
t2.start();
t1.start();
}
}
如何检测死锁:
两种方法
(1)找到本机jconsole程序,直接在windows系统搜索就可以,打开是这个样子。
然后在本地进程里面选择你的进程,其实就是你的项目名称。然后点击连接,在点击不安全连接。
进去之后点击线程
再点击检测死锁
最后就能看到死锁的线程了
(2)首先是在idea的控制台,打开Terminal,输入【jps】命令查看所有的进程id,找到你自己的java类名称对应的id。
然后输入【jstack + 进程号】 就可以查询到该进程的所有线程信息。在输出信息的最下面,就可以看到如下图所示的线程死锁信息。
2、死锁经典问题——哲学家就餐问题
经典场景:有四位哲学及在一正方形的桌子上面吃饭,桌子的每个角有一根筷子,一共四根,那么,当每个哲学家都拿起自己左边的筷子之后,再去拿自己右边的筷子的时候,就会发现自己右边没有筷子,这时哲学就就会等右边的哲学家放下筷子,但是每个哲学家都是这个想法,那么都不会放下筷子,并且都拿不到右边的筷子,因此就造成了死锁。
代码实现例子:
@Slf4j
public class Thread1 {
public static void main(String[] args) throws InterruptedException {
//筷子对象
Chopsticks c1 = new Chopsticks("c1");
Chopsticks c2 = new Chopsticks("c2");
Chopsticks c3 = new Chopsticks("c3");
Chopsticks c4 = new Chopsticks("c4");
new Philosopher("李云龙",c1,c2).start();
new Philosopher("赵刚",c2,c3).start();
new Philosopher("魏和尚",c3,c4).start();
new Philosopher("张大彪",c4,c1).start();
}
}
//筷子
class Chopsticks{
private String name;
public Chopsticks(String name) {
this.name = name;
}
}
//哲学家
@Slf4j
class Philosopher extends Thread{
//名字
private String name;
//筷子
private Chopsticks left;
private Chopsticks right;
public Philosopher(String name, Chopsticks left, Chopsticks right) {
super(name);
this.left = left;
this.right = right;
}
@Override
public void run() {
while(true){
synchronized (right){
synchronized (left){
eat(name);
}
}
}
}
private void eat(String name){
log.debug(name + "正在吃饭");
}
}
测试结果:可以实现吃饭操作,但是会出现场景中描述的问题,出现线程死锁。
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341