Java线程死锁

一种特殊类型的错误,需要避免对多任务具体涉及死锁,当两个线程有一个循环依赖于一对同步对象时发生。

例如,假设一个线程进入监视器对象X和其他线程进入监视器对象Y。如果在X中的线程试图调用Y上的任何synchronized方法,它会阻止预期。但是,如果在Y中的线程,反过来,尝试调用X上的任何synchronized方法,该线程将永远等待,因为访问的X,那就要释放自己的Y上的锁,使第一个线程可以完成。

例子:

要充分认识死锁看到它的实际是有用的。下一个示例创建两个类,A和B,具有方法foo()和bar(),分别为,其试图在其他类调用一个方法之前稍作停顿。

主类,命名为死锁,创建一个A和一个B实例,然后启动第二个线程来设置死锁条件。foo()和bar()方法使用sleep()方法,以此来迫使死锁情况发生。

class A {
   synchronized void foo(B b) {
      String name = Thread.currentThread().getName();
      System.out.println(name + " entered A.foo"); 
      try {
         Thread.sleep(1000);
      } catch(Exception e) {
         System.out.println("A Interrupted");
      }
      System.out.println(name + " trying to call B.last()");
      b.last();
   }
   synchronized void last() {
      System.out.println("Inside A.last");
   }
}
class B {
   synchronized void bar(A a) {
      String name = Thread.currentThread().getName();
      System.out.println(name + " entered B.bar");
      try {
         Thread.sleep(1000);
      } catch(Exception e) {
         System.out.println("B Interrupted");
      }
      System.out.println(name + " trying to call A.last()");
      a.last();
   }
   synchronized void last() {
      System.out.println("Inside A.last");
   }
}
public class Deadlock implements Runnable {
   A a = new A();
   B b = new B();
   Deadlock() {
      Thread.currentThread().setName("MainThread");
      Thread t = new Thread(this, "RacingThread");
      t.start();
      a.foo(b); // get lock on a in this thread.
      System.out.println("Back in main thread");
   }
   public void run() {
      b.bar(a); // get lock on b in other thread.
      System.out.println("Back in other thread");
   }
   public static void main(String args[]) {
      new Deadlock();
   }
}

下面是该程序的一些输出:

MainThread entered A.fooRacingThread entered B.barMainThread trying to call B.last()RacingThread trying to call A.last()

因为程序已经死锁时需要按Ctrl-C来结束程序。可以看到一个完整的线程,并通过按PC上的CTRL-BREAK监视缓存转储。

会看到RacingThread持有B上监视器,而它正在等待a监视器上。与此同时,MainThread拥有并正在等待获取湾这个程序将永远不会完成。

这个例子说明,如果多线程程序锁定偶然,死锁应该检查的首要条件之一。

顺序锁:

一个常见的​​线程伎俩来避免死锁是顺序锁。通过顺序锁,它给线程特定顺序获得多个锁。

死锁例子:

下面是一个死锁的描述:

// File Name ThreadSafeBankAccount.java public class ThreadSafeBankAccount { private double balance ; private int number ; public ThreadSafeBankAccount ( int num , double initialBalance ) { balance = initialBalance ; number = num ; } public int getNumber () { return number ; } public double getBalance () { return balance ; } public void deposit ( double amount ) { synchronized ( this ) { double prevBalance = balance ; try { Thread . sleep ( 4000 ); } catch ( InterruptedException e ) {} balance = prevBalance + amount ; } } public void withdraw ( double amount ) { synchronized ( this ) { double prevBalance = balance ; try { Thread . sleep ( 4000 ); } catch ( InterruptedException e ) {} balance = prevBalance - amount ; } } } // File Name LazyTeller.java public class LazyTeller extends Thread { private ThreadSafeBankAccount source , dest ; public LazyTeller ( ThreadSafeBankAccount a , ThreadSafeBankAccount b ) { source = a ; dest = b ; } public void run () { transfer ( 250.00 ); } public void transfer ( double amount ) { System . out . println ( "Transferring from " + source . getNumber () + " to " + dest . getNumber ()); synchronized ( source ) { Thread . yield (); synchronized ( dest ) { System . out . println ( "Withdrawing from " + source . getNumber ()); source . withdraw ( amount ); System . out . println ( "Depositing into " + dest . getNumber ()); dest . deposit ( amount ); } } } } public class DeadlockDemo { public static void main ( String [] args ) { System . out . println ( "Creating two bank accounts..." ); ThreadSafeBankAccount checking = new ThreadSafeBankAccount ( 101 , 1000.00 ); ThreadSafeBankAccount savings = new ThreadSafeBankAccount ( 102 , 5000.00 ); System . out . println ( "Creating two teller threads..." ); Thread teller1 = new LazyTeller ( checking , savings ); Thread teller2 = new LazyTeller ( savings , checking ); System . out . println ( "Starting both threads..." ); teller1 . start (); teller2 . start (); } }

这将产生以下结果:

Creating two bank accounts...
Creating two teller threads...
Starting both threads...
Transferring from 101 to 102
Transferring from 102 to 101
Withdrawing from 101
Depositing into 102
Withdrawing from 102
Depositing into 101
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值