Java 实例方法与实例变量的线程安全
我想知道一个类的每个实例是否都有该类中方法的副本 比如说,我有下面的类Java 实例方法与实例变量的线程安全,java,multithreading,Java,Multithreading,我想知道一个类的每个实例是否都有该类中方法的副本 比如说,我有下面的类MyClass: public MyClass { private String s1; private String s2; private String method1(String s1){ ... } private String method2(String s2){ ... } } 因此,如果两个不同的用户创建了MyClass的实例,比如:
MyClass
:
public MyClass {
private String s1;
private String s2;
private String method1(String s1){
...
}
private String method2(String s2){
...
}
}
因此,如果两个不同的用户创建了MyClass
的实例,比如:
MyClass instanceOfUser1 = new MyClass();
MyClass instanceOfUser2 = new MyClass();
知道每个用户的线程中都有MyClass
方法的副本吗?如果是,那么实例变量是线程安全的,只要只有实例方法操作它们,对吗
我问这个问题是因为我经常读到实例变量不是线程安全的。我不明白为什么会是这样,当每个用户通过调用
new
操作符获得一个实例时?在许多情况下,一个实例可以从多个类访问。例如,如果您的实例是另一个类中的静态变量,那么所有线程都将共享该实例,这样您可能会遇到大麻烦。这只是我想到的第一种方法…每个对象都有自己的类实例变量副本-它是类的所有实例之间共享的静态变量。实例变量不一定是线程安全的原因是,它们可能会被调用非同步实例方法的多个线程同时修改
class Example {
private int instanceVariable = 0;
public void increment() {
instanceVariable++;
}
}
现在,如果两个不同的线程同时调用increment
,那么您就有了一个数据竞争-instanceVariable
可能会在两个方法返回的末尾增加1或2。您可以通过将synchronized
关键字添加到increment
,或使用AtomicInteger
而不是int
等来消除这种数据竞争,但关键是,仅仅因为每个对象都有自己的类实例变量副本,并不一定意味着变量是以线程安全的方式访问的——这取决于类的方法。(例外情况是final
不可变变量,不能以线程不安全的方式访问,除非是像序列化黑客这样愚蠢的东西。)多线程问题主要出现在同时访问静态变量和类的实例时
您不应该担心类中的方法,而应该更多地关注字段(这意味着在类级别定义了范围)。如果存在对一个类实例的多个引用,则不同的执行路径可能会尝试同时访问该实例,从而导致意外后果,如竞争条件
类基本上是创建对象实例的蓝图。当对象被实例化时,它在内存中接收一个由引用访问的点。如果有多个线程具有此引用的句柄,则可能会导致同时访问实例的情况发生,这将导致两个线程操作字段。'instance Variables not thread safe'-此语句取决于上下文。
这是真的,如果你说的是servlet。这是因为,servlet只创建一个实例,多个线程访问它。因此,在这种情况下,实例变量不是线程安全的
在上述简化的情况下,如果要为每个线程创建新实例,那么实例变量是线程安全的
希望这能回答您的问题每个实例都有自己的实例变量集。您将如何检测每个实例是否都有不同的方法“副本”?只有通过检查实例变量的状态才能看到差异吗
事实上,没有,只有一个方法副本,这意味着调用该方法时执行的指令集。但是,在执行时,实例方法可以引用正在使用保留标识符this
调用它的实例。此
标识符引用当前实例。如果您不使用其他内容限定实例变量(或方法),则暗示此
比如说,
final class Example {
private boolean flag;
public void setFlag(boolean value) {
this.flag = value;
}
public void setAnotherFlag(Example friend) {
friend.flag = this.flag;
}
}
对于setFlag()
和setAnotherFlag()
方法,只有一个字节副本构成VM指令。但是当调用它们时,这个
被设置为发生调用的实例。因为this
是针对非限定变量的,所以您可以删除示例中对this
的所有引用,并且它的功能仍然完全相同
但是,如果一个变量是限定的,比如上面的
friend.flag
,则可以引用另一个实例的变量。这就是在多线程程序中遇到麻烦的原因。但是,只要一个对象没有从一个线程“逃逸”到其他线程可见,就没有什么可担心的。A方法
只不过是一组指令。无论哪个线程调用该方法,都要获取这些指令的副本。然后开始执行。该方法可以使用方法和线程范围的局部变量
,也可以使用共享资源,如静态资源、共享对象或其他资源,哪些是线程间可见的您是在询问每个线程都有自己的MyClass
实例,还是每个线程都有一个方法不同的MyClass
实例?没有实例变量本质上是线程安全的。如果两个线程可以修改对同一对象的引用,那么您需要实现某种类型的同步。您真的很困惑。线程安全与状态有关。状态是关于字段的,而不是关于方法的。类的线程安全性完全取决于方法如何使用字段s1和s2。没有它们的主体使问题无法回答。使MyClass不可变当然意味着这个问题不会出现。我问这个问题是因为我经常读到实例变量不是线程安全的。因为你的问题是