由于Spring的单态引起的线程阻塞的问题

 

线程阻塞的问题

关键字:Spring 单例,同步,线程阻塞,粒度

 

现象:某大型保险公司的OA应用(大集中模式,用户有2万多人,8千多个组织)在200多用户在线时,竟然发生了weblogic实例挂起,分析dump文件,发现有一个流程提交的线程发生意外,一直占有着一个对象的锁,因此它竟然阻塞了200多个线程,而所有的线程都阻塞在一个叫A的对象上,而这些被阻塞的线程还是处理不同的任务(就是说调用不同的方法),然后马上去看A.java的代码,发现这个类的所有方法都加了synchronized关键字,即都进行了同步,代码示例如下:

public class AImpl{

 

         public void synchronized test1(){

 

}

 

public void synchronized test2(){

 

}

 

public void synchronized test3(){

 

}

}

 

public class BImpl{

         private A a;

public void setA(A a){

         this.a = a;

}

public void b_test1(){

                   a.test1();

}

 

pubic void b_test2(){

         a.test2();

}

 

public void b_test3(){

         a.test3();

}

}

 

问题出来了,有一个线程在执行b_test1()方法,而线程2在执行b_test2()方法,线程3在执行b_test3()方法,结果后面2个线程都被线程1阻塞了,等待它释放持有的a对象的这把锁,为什么会这样呢?而看AImpl.java这个类,其实作者的目的只是希望test1test2test3这三个方法在同一个时刻各自只有一个线程执行(即test1在同一个时刻只能有一个线程执行,其它要执行test1的线程只能排队,而test1test2test3三个方法是可以并发执行的),但是真实的现象是:test1test2test3三个方法都在排对了!也就是说test2test3两个方法都在等待对象a的锁,而a的锁被执行test1方法的线程所持有了,为什么会这样呢,单例!突然想到了Springbean在默认情况下都是单态的,也就是说a对象在整个虚拟机都是唯一的!因此AImpl.java中的所有互不相干的方法都只能串行执行了!ohmy god

解决办法:

1、  AImpl.java拆分,也就说把test1test2test3三个方法分拆到三个类中去,这样就会有各自的实例,因此不再发生test1test2test3三个方法互相排队的事情发生

2、  利用一个小技巧,即我们不动AImpl.java的代码,只是在Springxxx.bean.xml的配置文件中,分别为test1test2test3三个方法配置三个实例就可以了(即a1a2a3),然后修改BImpl.java如下:

public class BImpl{

                   private A a1;

                   private A a2;

                   private A a3;

public void setA1(A a1){

         this.a1 = a1;

}

public void setA2(A a2){

         this.a2 = a2;

}

 

public void setA3(A a3){

         this.a3 = a3;

}

 

public void b_test1(){

                   a1.test1();

}

 

pubic void b_test2(){

         a2.test2();

}

 

public void b_test3(){

         a3.test3();

}

}

 

总结:解决问题的本质在于一定要明白synchronized关键字锁住的是实例对象,因此问题的发生和解决都是基于它的

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值