线程阻塞的问题
关键字: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这个类,其实作者的目的只是希望test1、test2、test3这三个方法在同一个时刻各自只有一个线程执行(即test1在同一个时刻只能有一个线程执行,其它要执行test1的线程只能排队,而test1、test2、test3三个方法是可以并发执行的),但是真实的现象是:test1、test2、test3三个方法都在排对了!也就是说test2、test3两个方法都在等待对象a的锁,而a的锁被执行test1方法的线程所持有了,为什么会这样呢,单例!突然想到了Spring的bean在默认情况下都是单态的,也就是说a对象在整个虚拟机都是唯一的!因此AImpl.java中的所有互不相干的方法都只能串行执行了!oh,my god!
解决办法:
1、 将AImpl.java拆分,也就说把test1、test2、test3三个方法分拆到三个类中去,这样就会有各自的实例,因此不再发生test1、test2、test3三个方法互相排队的事情发生
2、 利用一个小技巧,即我们不动AImpl.java的代码,只是在Spring的xxx.bean.xml的配置文件中,分别为test1、test2、test3三个方法配置三个实例就可以了(即a1,a2,a3),然后修改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关键字锁住的是实例对象,因此问题的发生和解决都是基于它的
分享到:
相关推荐
- 实现单态登录也可以借助成熟的SSO框架,如Spring Security、CAS(Central Authentication Service)等。这些框架提供了丰富的功能和自定义选项,能够简化开发过程。 综上所述,Java实现的单态登录涉及单态模式、...
9. **Spring Security**:在Java Web开发中,Spring Security是一个强大的安全框架,提供了单态登录的实现。通过配置它可以轻松地实现SSO功能,包括基于JWT(JSON Web Tokens)的身份验证和授权。 10. **Cookie与...
这种模式的出现主要是为了解决对象创建的控制问题,特别是在某些需要频繁创建和销毁的对象中,单态模式能有效地提高性能,减少系统资源的消耗。 在Java中,单态模式的实现通常有两种常见方式:饿汉式和懒汉式。饿汉...
单态模式(Singleton Pattern)是软件设计模式中的一种,它保证了类只有一个实例,并提供一个全局访问点。这种模式在很多场景下非常有用,比如配置管理、线程池、缓存管理和日志记录等,因为它可以确保在整个系统中...
单态模式(Singleton Pattern)是软件设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。在.NET环境中,无论是C#还是ASP.NET项目,单态模式都是经常被用到的设计模式之一,尤其在处理全局配置、...
在实际应用中,还需要考虑线程安全问题。如果多个线程同时调用`getInstance()`方法,则可能会创建多个实例。为了避免这种情况,可以采用同步方法或者双重检查锁定(Double-Checked Locking)的方式来确保线程安全性...
其中,Spring的核心设计理念体现在对两种基本设计模式的实现上:工厂模式和单态模式。 首先,工厂模式是Spring容器的核心。Spring作为一个bean工厂,负责管理和实例化应用中的各种bean。它遵循工厂模式的原则,使得...
是个使用java实现的单态例子,开始接触java单态的或是不了解单态是怎么实现的同僚,是个不错的参考
单态登录(Single Sign-On,简称SSO)是一种身份验证机制,允许用户在一次登录后访问多个相互关联的应用系统,而无需再次输入凭证。在Web开发领域,尤其是使用JSP和JavaWeb技术栈时,单态登录对于构建大型、多模块的...
为了解决懒汉式的线程安全问题,有以下两种方式: - **同步方法**:在`getInstance`上添加`synchronized`关键字,保证多线程环境下的安全性,但会降低效率。 ```java public class Singleton { private static ...
这个一个简单的java例子,可以为新手加深对java单态模式的理解.....
### Spring宝典知识点详解 #### 一、Spring框架概述及核心机制 - **Spring框架的起源与发展** - Spring框架自发布以来迅速成为最受欢迎的Java企业级应用开发框架之一,其核心价值在于提供了轻量级的IoC容器,极大...
2. **线程安全的实现**:为了解决多线程问题,可以使用`lock`关键字或`System.Threading.ThreadStatic`属性。例如,使用`lock`关键字实现线程安全的经典单态: ```csharp public class Singleton { private static ...
- 在分布式系统如EJB中,由于跨越服务器和JVM,单态模式可能失效,需要考虑其他设计方案。 - 单态模式使得系统难以扩展,如果需要改变或替换单态对象的行为,可能需要修改代码,这违背了开放封闭原则。 - 如果单态...
- 单例模式的线程安全问题:在多线程环境下,需要确保`GetInstance()`方法是线程安全的,可以使用互斥量(`CSingleLock`或`CWinThread::LockThreadCount`)来同步访问。 - 销毁单例:确保在程序结束时正确销毁单例...
单态模式的定义: Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。 在项目的很多地方都会用到它,比如说数据库的链接。 使用Singleton的好处还在于可以节省内存,因为它限制了实例...
单态模式(Singleton ...总结,单态模式是一种常用的软件设计模式,它能有效地控制资源的分配和使用,但在设计时也需要注意其可能带来的问题,如扩展性和并发处理。在实际开发中,应根据具体需求选择合适的设计模式。
单态模式是在面向对象设计中实现类似单例行为的一种替代方法,确保Java应用程序中的共享状态。它强制实现一种独特的行为,即类的所有实例共享相同的状态。与单例模式不同,单例模式将类限制为单个实例,单态模式允许...