旺财和小强的三生三世

作者:CQITer小编 时间:2019-01-15 21:37

字号

旺财和小强是线程池的两个线程, 他们经常做的工作就是对一个数加加减减,用人类的话来说就是存款,取款。

public class Account{ 

   private int balance; 

   public synchronized void deposit(int amt){ 

       balance += amt; 

   } 

 

   public synchronized void withdraw(int amt){ 

       if(balance >= amt){ 

           balance -= amt; 

       } 

       throw new RuntimeException("insufficent blance"); 

   } 

(友情提示,可左右滑动,下同)

每次进行存款,取款操作的时候,他们两个都需要获得一把锁,这样就能保证同一时刻只有一个人在修改,不会出乱子。

这一天,他们俩又遇到了一个叫做转账的操作:

public void transfer(Account from,Account toint amt){ 

   synchronized(from){ 

       synchronized(to){ 

           from.withdraw(amt); 

           to.deposit(amt); 

       } 

   } 

旺财说:“这个程序员不错,考虑得挺周全。转账的时候把两个账户都锁住了,安全!”

小强说:“没错,执行吧。”

旺财这个线程从A向B转账 , 与此同时,小强从B向A转账

令旺财和小强没有想到的是,居然出现了死锁。

旺财和小强的三生三世

类似的事件发生不少, 线程池的线程用光了,Tomcat被迫重启,这个世界毁灭了。

第二世

新生代的旺财和小强从线程池中出来, Tomcat老大给他们讲了上一代旺财和小强的故事, 对他们谆谆教导:“做转账操作的时候一定要小心,别死锁了!”

旺财和小强有点儿愤愤不平:“这我们俩也控制不了啊,这要看程序员写的代码,以及操作系统中的线程调度啊!”

不满归不满,他俩还是有点小期待,想看看可怕的转账代码到底怎么样。

没过多久, 他俩就如愿了:

public static final Object lock = new Object(); 

public void transfer(Account from,Account toint amt){ 

   int fromHash = System.identityHashCode(from); 

   int toHash = System.identityHashCode(to); 

   if(fromHash > toHash){ 

       synchronized(from){ 

           synchronized(to){ 

               from.withdraw(amt); 

               to.deposit(amt); 

           } 

       } 

   } 

   else if(toHash > fromHash){ 

       synchronized(to){ 

           synchronized(from){ 

               from.withdraw(amt); 

               to.deposit(amt); 

           } 

       } 

   } 

   else { 

       synchronized(lock){ 

           synchronized(from){ 

               synchronized(to){ 

                   from.withdraw(amt); 

                   to.deposit(amt); 

               } 

           } 

       } 

   } 

看到这样的代码, 旺财倒吸了一口气,挠着头说:“搞什么鬼,转个账都这么麻烦!”

责任编辑:CQITer新闻报料:400-888-8888   本站原创,未经授权不得转载
关键词 >>程序员 线程 Tomcat
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接