我有一个如下的代码
class classA {
int sum = 0;
void recursiveMethodA {
sum = sum +1; // For simplicity
}
}
基本上,我在递归方法中执行一些操作,该方法运行10次并在类级别更改状态。但是此类不是线程安全的。
现在为了使其线程安全,我在考虑以下选项。
class class B {
// Public exposed method
public void methodB {
ClassA classA = new ClassA();
classA.recursiveMethodA();
}
}
我的逻辑是,由于我是在类B的方法内创建类A的对象,因此它是在堆栈而不是堆上创建的,因此它是线程安全的。
这种逻辑正确吗?请提出其他选择。
答案 0 :(得分:2)
我的逻辑是,由于我是在类B的方法内创建类A的对象,因此它是在堆栈而不是堆上创建的,因此它是线程安全的。
您的逻辑和/或术语不正确。实际上,ClassA
的实例在堆中。所有常规的Java对象都在堆中创建!
您的代码实际上是线程安全的,但是正确的解释如下:
仅仅说使用局部变量是不够的:
在某些情况下,另一个线程可以看到局部变量的值。例如如果创建了lambda或内部方法闭包并将其传递给另一个线程。
还必须考虑可以将变量中的值传递给另一个线程。
完成和参考处理将在另一个线程上完成。但是,这不应引起线程安全问题。 (JLS规范负责终结,而Reference
的javadocs负责引用。在两种情况下,在适当的位置都出现了开头。)
1-这是一种奇特的说法,即没有其他线程可以看到该对象及其引用。
您是说classA本身是线程安全的吗?
不。它本身不是线程安全的。在这种特定情况下,它是线程安全的。或更重要的是,在这种情况下,线程安全是无济于事的……因为实例是线程受限的。
我不是应该在所有上下文中都将该类定义为线程安全的吗?我不知道明天怎么用?
由您决定!
但是请考虑以下问题:大量标准Java类并非设计成线程安全的。确实,经典情况是StringBuilder
,它是StringBuffer
的非线程安全重新实现。其他java.util
中的大多数集合类型!
基本上,您有两种选择:
使类具有固有的线程安全性,并接受运行时开销。
使类本质上是非线程安全的,并确保仅使用适当地处理该类的方式。 (一种方法是线程限制实例。另一种方法是使用某种形式的外部同步。)
答案 1 :(得分:-3)
拥有线程安全功能的最简单方法是将关键字“ synchronized”放入
synchronized public void method() {
//do something
}