JAVA多线程机制之死锁

同步特性使用起来非常方便,功能很强大。但有的时候考虑不周的话有可能出现线程死锁。死锁主要是多个线程争抢资源造成的。
下面通过一个例子演示死锁:

class Resource
{
   private int res = 0;

   public int getRes()
   {
      return res;
   }

   public void setRes(int res)
   {
      this.res = res;
   }

}

class DeadLock1 extends Thread
{
   Resource res1 = null;
   Resource res2 = null;

   public DeadLock1(String name, Resource res1, Resource res2)
   {
      super(name);
      this.res1 = res1;
      this.res2 = res2;
   }

   @Override
   public void run()
   {
      // 获取res1的锁从而锁住res1
      synchronized (res1)
      {
         for (int i = 0; i < 10; i++)
         {
            int r = res1.getRes();
            r++;
            res1.setRes(r);
         }
         System.out.println(getName() + ":资源1处理完毕等待资源2...");
         try
         {
            Thread.sleep(1000);
         }
         catch (InterruptedException e)
         {
            System.out.println(getName() + "异常中断");
         }
         // 此时res1并未释放
         // 获取res2的锁从而锁住res2
         synchronized (res2)
         {
            for (int i = 0; i < 10; i++)
            {
               int r = res2.getRes();
               r++;
               res2.setRes(r);
            }
            System.out.println(getName() + ":资源2处理完毕...");
         }
      }
   }
}

class DeadLock2 extends Thread
{
   Resource res1 = null;
   Resource res2 = null;

   public DeadLock2(String name, Resource res1, Resource res2)
   {
      super(name);
      this.res1 = res1;
      this.res2 = res2;
   }

   @Override
   public void run()
   {
      // 获取res1的锁从而锁住res2
      synchronized (res2)
      {
         for (int i = 0; i < 10; i++)
         {
            int r = res2.getRes();
            r++;
            res2.setRes(r);
         }
         System.out.println(getName() + ":资源2处理完毕等待资源1...");
         try
         {
            Thread.sleep(1000);
         }
         catch (InterruptedException e)
         {
            System.out.println(getName() + "异常中断");
         }
         // 此时res2并未释放
         // 获取res1的锁从而锁住res1
         synchronized (res1)
         {
            for (int i = 0; i < 10; i++)
            {
               int r = res1.getRes();
               r++;
               res1.setRes(r);
            }
            System.out.println(getName() + ":资源1处理完毕...");
         }
      }
   }
}

public class DeadLockDemo
{
   public static void main(String[] args)
   {
      // 新建共享资源
      Resource res1 = new Resource();
      Resource res2 = new Resource();
      DeadLock1 lock1 = new DeadLock1("线程1", res1, res2);
      DeadLock2 lock2 = new DeadLock2("线程2", res1, res2);
      lock1.start();
      lock2.start();
   }
}

运行结果:
线程1:资源1处理完毕等待资源2…
线程2:资源2处理完毕等待资源1…

程序说明:线程1和线程2共享资源res1和res2,当线程1首先运行获取资源res1的锁从而锁住res1,调用sleep()使线程2得以运行,此时资源res1还未释放。线程2锁住资源res2,调用sleep(),线程1运行,此时资源res2还未释放,线程1尝试获取资源res2但是已经被线程2锁住,线程2睡眠过后开始运行尝试获取资源res1的锁但是已经被线程1锁住。此时线程1和线程2处于死锁状态。

时间: 2024-11-03 20:46:42

JAVA多线程机制之死锁的相关文章

JAVA多线程机制之同步与互斥

一个多线程的程序,两个或者多个线程可能需要访问同一个数据资源.这时就必须考虑数据安全的问题,需要线程互斥或者同步. 线程的互斥 当多个线程需要访问同一资源时,要求在一个时间段内只能允许一个线程来操作共享资源,操作完毕后别的线程才能读取该资源,这叫线程的互斥.我们需要使用synchronized来给共享区域加锁,确保共享资源安全. 如果一个线程调用了某个对象的synchronized方法,它在这个方法运行完之前不会被别的线程打断,这就是线程的同步机制.一般将共享资源放在这个同步方法内部,这样就保证

Java多线程--同步与死锁:synchronized;等待与唤醒:wait、notify、notifyAll;生命周期

1.问题的引出 class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ for(int i=0;i<100;i++){ if(ticket>0){ // 还有票 try{ Thread.sleep(300) ; // 加入延迟 }catch(InterruptedException e){ e.printStackTrace() ; } System.out.prin

JAVA多线程机制之线程概念

在操作系统中,一个独立的正在运行的程序称为进程,通常一个程序又被分为称作任务的小块,任务又可以进一步分为称作线程的更小的块.如果一个程序多于一个线程同时执行,就可以称为多线程并行. 一个线程被定义为一个单一的连续控制流,线程也可以成为执行环境或者轻量级程序.当一个程序发起之后,会首先生成一个缺省的线程,这个线程被称作主线程,就是由main方法引导进入的线程,main方法调用的方法结构会在这个主线程中顺序执行.如果在线程中新建并启动的线程称为从线程.从线程也有自己的入口方法,这是由开发者自己定义的

JAVA多线程机制之暂停、恢复和停止

在JDK1.2以前的版本如果要实现线程的暂停.恢复和停止的方法分别是suspend().resume().stop().但是从JDK1.2以后这些方法已经被遗弃,因为它们有可能造成严重的系统错误和异常. 首先suspend()方法不会释放线程所占用的资源.如果使用该方法将某个线程挂起,则可能会使其他等待资源的线程死锁.而resume()方法本身并无问题,但是不能独立于suspend()方法存在. 其次调用stop()可能会导致严重的系统故障.因为该方法会使线程立刻中断指令执行,不管这段方法是否执

JAVA多线程机制之线程创建

在Java中创建线程有两种方式,一种是继承Thread,另一种是实现Runnable接口,Thread实际上也实现了Runnable接口. Thread 构造方法 方法名 说明 Thread() 分配新的 Thread 对象 Thread(Runnable target) 分配新的 Thread 对象 Thread(Runnable target, String name) 分配新的 Thread 对象 Thread(String name) 分配新的 Thread 对象 Thread(Thre

40个Java多线程问题总结

前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题. 这些多线程的问题,有些来源于各大网站.有些来源于自己的思考.可能有些问题网上有.可能有些问题对应的答案也有.也可能有些各位网友也都看过,但是本文写作的重心就是所有的问题都会按照自己的理解回答一遍,不会去看网上的答案,因此可能有些问题讲的不对,能指正的希望大家不

分享40个Java多线程问题小结_java

Java多线程是什么 Java提供的并发(同时.独立)处理多个任务的机制.多个线程共存于同一JVM进程里面,所以共用相同的内存空间,较之多进程,多线程之间的通信更轻量级.依我的理解,Java多线程完全就是为了提高CPU的利用率.Java的线程有4种状态,新建(New).运行(Runnable).阻塞(Blocked).结束(Dead),关键就在于阻塞(Blocked),阻塞意味着等待,阻塞的的线程不参与线程分派器(Thread Scheduler)的时间片分配,自然也就不会使用到CPU.多线程环

一个java多线程的问题

问题描述 一个java多线程的问题 为什么代码中线程VolatileExample 不会终止 package thread; public class VolatileExample extends Thread{ private static boolean flag = false; @Override public void run() { while (!flag) { //System.out.println(1); } } public static void main(String

Java 多线程 死锁 隐性死锁 数据竞争 恶性数据竞争 错误解决深入分析 全方向举例

在几乎所有编程语言中,由于多线程引发的错误都有着难以再现的特点,程序的死锁或其它多线程错误可能只在某些特殊的情形下才出现,或在不同的VM上运行同一个程序时错误表现不同.因此,在编写多线程程序时,事先认识和防范可能出现的错误特别重要.无论是客户端还是服务器端多线程Java程序,最常见的多线程问题包括死锁.隐性死锁和数据竞争. Java线程死锁如何避免这一悲剧  Java线程死锁需要如何解决,这个问题一直在我们不断的使用中需要只有不断的关键.不幸的是,使用上锁会带来其他问题.让我们来看一些常见问题以