java多线程基本概述(四)——死锁

package mytask;

public class Task {
    public static void main(String[] args) {
        DeadThread thread = new DeadThread();
        Thread t1 = new Thread(thread);
        t1.setName("a");
        Thread t2 = new Thread(thread);
        t2.setName("b");
        t1.start();
        t2.start();
    }    
}

class DeadThread implements Runnable{
    private String o1= new String("o1");
    private String o2 = new String("o2");
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("a")){
            synchronized(o1){
                System.out.println("a thread  enter outer monitor o1....");
                try{
                    Thread.sleep(3000);
                    System.out.println("a waiting for o2 monitor...");
                    synchronized(o2){
                        System.out.println("a thread enter inner monitr o2");
                    }
                }catch(InterruptedException e){
                    e.printStackTrace();
                }                
            }
        }else{
            synchronized(o2){
                System.out.println("b thread  enter outer monitor o1....");
                try{
                    Thread.sleep(3000);
                    System.out.println("b waiting for o1 monitor...");
                    synchronized(o1){
                        System.out.println("b thread enter inner monitr o1");
                    }
                }catch(InterruptedException e){
                    e.printStackTrace();
                }                
            }
        }
    }
    
}

输出结果:

a thread  enter outer monitor o1....
b thread  enter outer monitor o1....
a waiting for o2 monitor...
b waiting for o1 monitor...

一致处于阻塞状态,可以通过jps命令查看信息得到

8064 Task
3832
3388 Jps

然后再执行 jstack -l 8064 

得到信息

Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.6-b01 mixed mode):

"DestroyJavaVM" prio=6 tid=0x000000000096c000 nid=0x494 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"b" prio=6 tid=0x0000000006d66800 nid=0x548 waiting for monitor entry [0x000000000772f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at mytask.DeadThread.run(Task.java:40)
        - waiting to lock <0x00000007c099b648> (a java.lang.String)
        - locked <0x00000007c099b668> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:662)

   Locked ownable synchronizers:
        - None

"a" prio=6 tid=0x0000000006d66000 nid=0x1354 waiting for monitor entry [0x000000000762f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at mytask.DeadThread.run(Task.java:27)
        - waiting to lock <0x00000007c099b668> (a java.lang.String)
        - locked <0x00000007c099b648> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:662)

   Locked ownable synchronizers:
        - None

"Low Memory Detector" daemon prio=6 tid=0x00000000025bf000 nid=0x1890 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C2 CompilerThread1" daemon prio=10 tid=0x00000000025b5800 nid=0x1bb8 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C2 CompilerThread0" daemon prio=10 tid=0x00000000025ac800 nid=0x1ee8 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Attach Listener" daemon prio=10 tid=0x00000000025ab800 nid=0x480 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Signal Dispatcher" daemon prio=10 tid=0x00000000025a8800 nid=0xebc runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Finalizer" daemon prio=8 tid=0x0000000002592000 nid=0x1dd0 in Object.wait() [0x0000000006d2f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000007c0961300> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
        - locked <0x00000007c0961300> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

   Locked ownable synchronizers:
        - None

"Reference Handler" daemon prio=10 tid=0x000000000258e800 nid=0x1560 in Object.wait() [0x0000000006c2f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000007c09611d8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:485)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
        - locked <0x00000007c09611d8> (a java.lang.ref.Reference$Lock)

   Locked ownable synchronizers:
        - None

"VM Thread" prio=10 tid=0x0000000002588000 nid=0x1d38 runnable

"GC task thread#0 (ParallelGC)" prio=6 tid=0x00000000024e1800 nid=0x1e40 runnable

"GC task thread#1 (ParallelGC)" prio=6 tid=0x00000000024e3000 nid=0x1854 runnable

"GC task thread#2 (ParallelGC)" prio=6 tid=0x00000000024e4800 nid=0x1e00 runnable

"GC task thread#3 (ParallelGC)" prio=6 tid=0x00000000024e6800 nid=0x970 runnable

"VM Periodic Task Thread" prio=10 tid=0x00000000025c2000 nid=0xf00 waiting on condition

JNI global references: 882


Found one Java-level deadlock:
=============================
"b":
  waiting to lock monitor 0x0000000002598548 (object 0x00000007c099b648, a java.lang.String),
  which is held by "a"
"a":
  waiting to lock monitor 0x0000000002595de8 (object 0x00000007c099b668, a java.lang.String),
  which is held by "b"

Java stack information for the threads listed above:
===================================================
"b":
        at mytask.DeadThread.run(Task.java:40)
        - waiting to lock <0x00000007c099b648> (a java.lang.String)
        - locked <0x00000007c099b668> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:662)
"a":
        at mytask.DeadThread.run(Task.java:27)
        - waiting to lock <0x00000007c099b668> (a java.lang.String)
        - locked <0x00000007c099b648> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:662)

Found 1 deadlock.

死锁的一个经典场景为哲学家就餐问题。 产生死锁的原因主要是:

(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

死锁的解除与预防:
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和
解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确
定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态
的情况下占用资源。因此,对资源的分配要给予合理的规划。

转载于:https://www.cnblogs.com/soar-hu/p/6724174.html

### Java多线程学习资源 对于希望深入学习Java多线程相关内容的学习者来说,韩顺平老师的教程是一个非常不错的起点。以下是关于如何通过其课程及相关资料掌握Java多线程技术的具体说明。 #### 一、基础知识概述 Java中的多线程编程允许程序在同一时间内执行多个任务。一个多线程的应用可以通过创建多个线程来实现并发操作[^2]。具体而言,在Java中创建线程主要有两种方法:继承`Thread`类并重写`run()`方法[^1];或者实现`Runnable`接口并通过传递该接口实例给`Thread`对象完成线程启动[^3]。 #### 二、推荐的教学内容与视频 韩顺平老师在其《Java多线程基础》章节中详细讲解了上述两种线程创建方式及其应用场景。此外,他还介绍了更多高级主题,例如: - **线程生命周期**:从新建到终止的不同状态转换过程。 - **同步机制**:解决共享数据访问冲突的方法,如`synchronized`关键字的使用。 - **线程间通信**:利用等待/通知模式(`wait()`, `notify()`)协调不同线程的行为。 - **死锁预防**:分析可能导致死锁的情况以及相应的解决方案。 如果想进一步实践这些理论知识,则可以参考他所设计的一些案例研究,像模拟银行账户转账场景下的原子性和一致性保障措施等实际问题处理技巧[^4]。 #### 三、代码示例展示 以下提供了一个简单的基于继承`Thread`类的方式创建新线程的例子: ```java class MyThread extends Thread { public void run() { System.out.println("This is a thread created by extending Thread class."); } } public class Main { public static void main(String[] args) { MyThread t = new MyThread(); t.start(); // Start the thread. } } ``` 另一种更灵活的做法是采用`Runnable`接口形式定义线程逻辑: ```java class Task implements Runnable { @Override public void run() { System.out.println("A task implemented via Runnable interface."); } } public class Runner { public static void main(String[] args){ Thread thd = new Thread(new Task()); thd.start(); // Launches execution of our runnable object inside this newly formed thread context. } } ``` 以上两段代码分别展示了如何运用不同的策略去构建独立运行路径,并最终达到相同目的——即让指定功能作为单独流程被执行起来。 #### 、扩展阅读建议 除了观看在线教育平台上的官方录制版本外,还可以查阅一些经典书籍加深理解程度,比如《Effective Java》第三版里有关于高效管理多线程环境部分的内容讨论;或者是针对特定领域需求探索开源项目源码也是极佳途径之一。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值