我想知道 Spring 单例 bean 是否是线程安全的,如果是,那么为什么,如果不是,那么为什么?
由于我是春天的初学者,因此将不胜感激。
不,这两个概念甚至不相关。
单例是关于创造的。这种设计模式确保只创建一个类的一个实例。
线程安全与执行有关。引用维基百科:
如果一段代码只以保证多个线程同时安全执行的方式操作共享数据结构,那么它就是线程安全的。
所以最终线程安全取决于代码和代码。这就是 Spring bean 本身不是线程安全的原因。
我有不同的看法:Spring 单例 bean 创建一次,在任何时间点都只能有一个实例可用。
假设您有一个在非同步方法中修改的实例变量。在多线程环境中,相同的类实例将分配给所有线程,并且 2 个并发线程可以更新/更改实例变量,这可能会导致意外情况。单例 bean 不提供线程安全,现在您知道实例变量的使用可能会导致意外结果,您有 2 个选项来解决相同的问题:
Spring 单例 bean 不是线程安全的,因为 Spring 实例化了它们。对不起。
Spring 只是管理单例 bean 的生命周期并维护对象的单个实例。线程安全与它无关。
如果不是那为什么?
因为单例和线程安全是两个不同的概念。您可以使用 synchronized 关键字来确保线程安全
Singleton Beans 是否是线程安全的,取决于作用域为单例的类是如何编写的。每个调用线程将有自己的执行,并且不会干扰另一个线程的执行,除非在所有调用线程共享的单例作用域类中有一些代码。例如,如果一个类具有全局声明的变量,该变量正在被其方法访问,并且值被修改然后这可能会导致并发问题,因此最好将这些变量放在方法级别而不是类级别。
根据我的观点,你的单例类的线程安全完全取决于你设计/编写了你的单例类。
如果有任何全局变量定义了单例类,那么它将不是线程安全的,因为如果多个线程共享单例对象并执行可以更新全局变量的方法,它将不是线程安全的。
为了使任何单例类线程安全,建议使该类无状态意味着您应该避免在单例类中定义全局变量。
不,Spring singelton bean 不是线程安全的,这是示例
public class Emmloyee {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
这是applicationContext.xml
<bean id="emp" class="com.manikant.Emmloyee" p:id="26" p:name="Manikant Gautam">
这是测试课
public class Test {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("com/manikant/config.xml");
Emmloyee emp=(Emmloyee)ctx.getBean("emp");
System.out.println("User "+emp.getName() + " is of age "+emp.getId());
emp.setName("Changed value");
Emmloyee emp1=(Emmloyee)ctx.getBean("emp");
System.out.println("User "+emp1.getName() + " is of age "+emp1.getId());
}
}
这是输出
User Manikant Gautam is of age 26
User Changed name is of age 26
变化中value
所emp.setName("Changed value");
反映的bean emp1
也不同。
Spring 不保证线程安全。这将是你的责任。Spring 将创建一个 Singleton ,但如果它是可变的,那么它可能不是线程安全的。以这种方式处理spring bean类是程序员的责任,它应该是线程安全的。
上游使用并行处理调用了我的服务,它使我的应用程序崩溃。当线程 1 在 beanA 上工作时,另一个请求到达并设置了 beanA 的一些参数。当我的 beanA 存储在数据库中时,我确认它是一团糟。我使用原型修复了它。
在 Spring 中,单例 bean 不会有任何状态(无状态)。单例 bean 范围确保每个 BeanFactory 的单个实例。因此,在多线程环境中,即使使用单例 bean 范围,它也不能保证单个实例。
因此,为了解决这个问题,我们需要将 bean 范围从单例范围更改为原型范围,因为确保线程安全是开发人员的责任。
如果不是那为什么?
因为您可以在单例中引用非线程安全对象。
但是,如果您不这样做,并且您使用 spring 注入任何实例变量,那么是的,它们是线程安全的。