简体   繁体   English

Java中单实例方法上的线程安全

[英]thread safety on single instance method in java

If I have one instance of an object A and it has an instance method foo() with only variables created and used in that method is that method thread safe even if the same instance is accessed by many threads? 如果我有一个对象A的实例,并且它有一个实例方法foo(),该实例方法只有在该方法中创建和使用的变量,即使同一实例被许多线程访问,该方法线程是否安全?

If yes, does this still apply if instance method bar() on object A creates many threads and calls method foo() in the text described above? 如果是,如果对象A上的实例方法bar()创建许多线程并在上述文本中调用方法foo(),这是否仍然适用?

Does it mean that every thread gets a "copy" of the method even if it belongs to the same instance? 这是否意味着每个线程即使属于同一个实例,也会获得该方法的“副本”?

I have deliberately not used the synchronized keyword. 我故意不使用synced关键字。

Thanks 谢谢

Yes. 是。 All local variables (variables defined within a method) will be on their own Stack frame. 所有局部变量(在方法中定义的变量)将位于其自己的堆栈框架中。 So, they will be thread safe, provided a reference is not escaping the scope (method) 因此,如果引用未转义范围(方法),它们将是线程安全的

Note : If a local reference escapes the method (as an argument to another method) or a method works on some class level or instance level fields, then it is not thread-safe. 注意:如果本地引用转义了该方法(作为另一个方法的参数)或某个方法在某些类级别或实例级别字段上工作,则它不是线程安全的。

Does it mean that every thread gets a "copy" of the method even if it belongs to the same instance 这是否意味着每个线程即使属于同一个实例,也会获得该方法的“副本”

No, there will be only one method. 不,只有一种方法。 every thread shares the same method. 每个线程共享相同的方法。 But each Thread will have its own Stack Frame and local variables will be on that thread's Stack frame. 但是每个线程都有自己的堆栈框架,局部变量将位于该线程的堆栈框架上。 Even if you use synchronize on local Objects, Escape Analysis proves that the JVM will optimize your code and remove all kinds of synchronization. 即使您在本地对象上使用同步, Escape Analysis也会证明JVM将优化您的代码并删除所有类型的同步。

example : 例如:

public static void main(String[] args) {

    Object lock = new Object();
    synchronized (lock) {
        System.out.println("hello");
    }
}

will be effectively converted to : 将有效地转换为:

public static void main(String[] args) {

        Object lock = new Object(); // JVm might as well remove this line as unused Object or instantiate this on the stack
        System.out.println("hello");

}

You have to separate the code being run , and the data being worked on . 您必须分离正在运行代码正在处理数据

The method is code, executed by each of the threads. 该方法是由每个线程执行的代码。 If that code contains a statement such as int i=5 which defines a new variable i, and sets its value to 5, then each thread will create that variable. 如果该代码包含诸如int i=5类的语句,该语句定义了一个新变量i,并将其值设置为5,则每个线程将创建该变量。

The problem with multi-threading is not with common code, but with common data (and other common resources). 多线程问题不在于通用代码,而在于通用数据(和其他通用资源)。 If the common code accesses some variable j that was created elsewhere, then all threads will access the same variable j , ie the same data. 如果公共代码访问在其他位置创建的某个变量j ,则所有线程将访问相同的变量j ,即相同的数据。 If one of these threads modifies the shared data while the others are reading, all kinds of errors might occur. 如果其中一个线程在其他线程正在读取时修改了共享数据,则可能会发生各种错误。

Now, regarding your question, your code should be thread safe as long as your variables are defined within bar(), and bar() doesn't access some common resource such as a file. 现在,关于您的问题,您的代码应该是线程安全的,只要您的变量在bar()中定义,并且bar()不会访问某些常用资源(例如文件)。

You should post some example code to make sure we understand the use case. 您应该发布一些示例代码,以确保我们理解用例。

For this example: 对于此示例:

public class Test {
    private String varA;

    public void doSomething() {
        String varB;

    }
}

If you don't do anything to modify varA in this example and only modify varB , this example is Thread Safe. 如果在此示例中您不做任何修改varA ,而仅修改varB ,则此示例是线程安全的。

If, however, you create or modify varA and depend on it's state, then the method is NOT Thread Safe. 但是,如果您创建或修改varA并依赖于它的状态,则该方法不是线程安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM