`
snowfox2008
  • 浏览: 127493 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

由于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关键字锁住的是实例对象,因此问题的发生和解决都是基于它的

 

分享到:
评论
2 楼 snowfox2008 2009-08-05  
kuaiyuelaogong 写道
兄弟,说一句,spring的单键只是在spring的容器内的单键,而非整个jvm的,就是说他的单键和传统的单键是有区别的,传统单键无论是构造器私有化还是枚举实现都是jvm级别的。

还有就是,你会这个问题只要搞三个锁不就行了吗,又不用改变原先类的方式也不需要才分类啊。

解决问题是不是有些经验欠佳啊^_^


呵呵,回复如下:
第一点,我看了Spring的文档,确实是我搞错了,它的单例是在当前上下文中唯一的,实际上是对于引用当前ID的bean来说是唯一的,在此因为此文的误导,给大家道歉。也十分感谢kuaiyuelaogong兄的指正。

第二点,我给出了2个方案,第二个方案就是不用改变原先类的方式,只需要让Spring创建三个实例就可以了。其实这一点也正式对第一点的一个印证。



1 楼 kuaiyuelaogong 2009-07-31  
兄弟,说一句,spring的单键只是在spring的容器内的单键,而非整个jvm的,就是说他的单键和传统的单键是有区别的,传统单键无论是构造器私有化还是枚举实现都是jvm级别的。

还有就是,你会这个问题只要搞三个锁不就行了吗,又不用改变原先类的方式也不需要才分类啊。

解决问题是不是有些经验欠佳啊^_^

相关推荐

    Java实现的单态登陆

    - 实现单态登录也可以借助成熟的SSO框架,如Spring Security、CAS(Central Authentication Service)等。这些框架提供了丰富的功能和自定义选项,能够简化开发过程。 综上所述,Java实现的单态登录涉及单态模式、...

    单态登录——只能在一个机器上登录(完整实例)

    9. **Spring Security**:在Java Web开发中,Spring Security是一个强大的安全框架,提供了单态登录的实现。通过配置它可以轻松地实现SSO功能,包括基于JWT(JSON Web Tokens)的身份验证和授权。 10. **Cookie与...

    单态模式(PPT)

    这种模式的出现主要是为了解决对象创建的控制问题,特别是在某些需要频繁创建和销毁的对象中,单态模式能有效地提高性能,减少系统资源的消耗。 在Java中,单态模式的实现通常有两种常见方式:饿汉式和懒汉式。饿汉...

    单态模式(代码)

    单态模式(Singleton Pattern)是软件设计模式中的一种,它保证了类只有一个实例,并提供一个全局访问点。这种模式在很多场景下非常有用,比如配置管理、线程池、缓存管理和日志记录等,因为它可以确保在整个系统中...

    Net单态模式的案例

    单态模式(Singleton Pattern)是软件设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。在.NET环境中,无论是C#还是ASP.NET项目,单态模式都是经常被用到的设计模式之一,尤其在处理全局配置、...

    Java中单态设计模式

    在实际应用中,还需要考虑线程安全问题。如果多个线程同时调用`getInstance()`方法,则可能会创建多个实例。为了避免这种情况,可以采用同步方法或者双重检查锁定(Double-Checked Locking)的方式来确保线程安全性...

    Spring设计思想.ppt

    其中,Spring的核心设计理念体现在对两种基本设计模式的实现上:工厂模式和单态模式。 首先,工厂模式是Spring容器的核心。Spring作为一个bean工厂,负责管理和实例化应用中的各种bean。它遵循工厂模式的原则,使得...

    java单态例子

    是个使用java实现的单态例子,开始接触java单态的或是不了解单态是怎么实现的同僚,是个不错的参考

    单态登录的源代码

    单态登录(Single Sign-On,简称SSO)是一种身份验证机制,允许用户在一次登录后访问多个相互关联的应用系统,而无需再次输入凭证。在Web开发领域,尤其是使用JSP和JavaWeb技术栈时,单态登录对于构建大型、多模块的...

    MyEclipse\单态.rar

    为了解决懒汉式的线程安全问题,有以下两种方式: - **同步方法**:在`getInstance`上添加`synchronized`关键字,保证多线程环境下的安全性,但会降低效率。 ```java public class Singleton { private static ...

    简单的Java单态例子

    这个一个简单的java例子,可以为新手加深对java单态模式的理解.....

    spring 宝典

    ### Spring宝典知识点详解 #### 一、Spring框架概述及核心机制 - **Spring框架的起源与发展** - Spring框架自发布以来迅速成为最受欢迎的Java企业级应用开发框架之一,其核心价值在于提供了轻量级的IoC容器,极大...

    .Net单态模式的案例

    2. **线程安全的实现**:为了解决多线程问题,可以使用`lock`关键字或`System.Threading.ThreadStatic`属性。例如,使用`lock`关键字实现线程安全的经典单态: ```csharp public class Singleton { private static ...

    单态模式的设计和应用

    - 在分布式系统如EJB中,由于跨越服务器和JVM,单态模式可能失效,需要考虑其他设计方案。 - 单态模式使得系统难以扩展,如果需要改变或替换单态对象的行为,可能需要修改代码,这违背了开放封闭原则。 - 如果单态...

    mfc单态模式的例子

    - 单例模式的线程安全问题:在多线程环境下,需要确保`GetInstance()`方法是线程安全的,可以使用互斥量(`CSingleLock`或`CWinThread::LockThreadCount`)来同步访问。 - 销毁单例:确保在程序结束时正确销毁单例...

    JAVA设计模式(单态模式和简单工厂模式)

    单态模式的定义: Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。 在项目的很多地方都会用到它,比如说数据库的链接。 使用Singleton的好处还在于可以节省内存,因为它限制了实例...

    单态模式的练习

    单态模式(Singleton ...总结,单态模式是一种常用的软件设计模式,它能有效地控制资源的分配和使用,但在设计时也需要注意其可能带来的问题,如扩展性和并发处理。在实际开发中,应根据具体需求选择合适的设计模式。

    【Java设计模式】单态模式

    单态模式是在面向对象设计中实现类似单例行为的一种替代方法,确保Java应用程序中的共享状态。它强制实现一种独特的行为,即类的所有实例共享相同的状态。与单例模式不同,单例模式将类限制为单个实例,单态模式允许...

Global site tag (gtag.js) - Google Analytics