实现一个线程死锁

要想实现线程死锁,首先要清楚线程死锁的四个条件

  1. 互斥条件:一个资源每次只能被一个进程使用,即在一段时间内某资源仅为一个进程所使用。此时如果有其它进程请求该资源,则请求进程只能等待。
  2. 请求和保持条件:进程中已经保持了至少一个资源,但又提出了新的资源请求,而该资源已经被其它进程占用,此时请求进程被阻塞,但对它自己已经获得的资源保持不放。
  3. 不可剥夺条件:进程未使用完的资源在未使用完毕之前,不能被其它进程强行夺走,即只能由获得该资源的进程自己来释放
  4. 循环等待条件:若干进程间形成首尾相接循环等待资源的关系。在发生死锁时必然存在一个进程等待列队{P1, P2, ..., Pn},其中P1等待P2占有的资源,P2等待P3占有的资源....,Pn等待P1占有的资源。形成一个进程等待环路,环路中每一个进程所占有的资源同时被同一个申请。
class MyThread extends Thread{
  //类属性被所有实例共享
  static Object o1 = new Object();
  static Object o2 = new Object();
  
  public MyThread(int flag){
    this.flag = flag;
  }
  
  @Override
  public void run(){
    if(flag == 0){
      // 若flag==0 锁住o1
      synchronized(o1){
        System.out.println(flag + "锁住了o1");
        // 线程睡眠,让出cpu,但不释放锁
        Thread.sleep(1000);
        // 请求锁对象o2,但o2被flag==1占用
        synchronized(o2){
          System.out.println(flag + "锁住了o2");
        }
      }
      // 线程死锁,无法继续执行
      System.out.println(flag + "释放了o1和o2");
    }
    
    if(flag == 1){
      // 若flag==1 锁住o2
      synchronized(o2){
        System.out.println(flag + "锁住了o2");
        // 线程睡眠,让出cpu,但不释放锁
        Thread.sleep(1000);
        // 请求锁对象o1,但o1被flag==0占用
        synchronized(o1){
          System.out.println(flag + "锁住了o1");
        }
        // 线程死锁,无法继续执行
        System.out.println(flag + "释放了o1和o2");
      }
    }
  }
}

public class ThreadDeadLock{
  public static void main(String[] args){
    MyThread t1 = new MyThread(0);
    MyThread t2 = new MyThread(1);
    t1.start();
    t2.start();
  }
}
上一篇:安排工作以达到最大收益


下一篇:2021-11-4