【问题标题】:thread safety on single instance method in javajava中单实例方法的线程安全
【发布时间】:2014-10-07 00:34:42
【问题描述】:

如果我有一个对象 A 的实例,并且它有一个实例方法 foo(),并且只有在该方法中创建和使用的变量,即使同一个实例被许多线程访问,该方法是否是线程安全的?

如果是,如果对象 A 上的实例方法 bar() 创建了许多线程并调用了上述文本中的方法 foo(),这是否仍然适用?

这是否意味着每个线程都会获得该方法的“副本”,即使它属于同一个实例?

我故意不使用 synchronized 关键字。

谢谢

【问题讨论】:

  • 根据你的描述我不知道。如果局部变量是由本身不是线程安全的方法初始化的,那么foo() 也不是那么好。你有一些代码可以分享吗?

标签: java multithreading


【解决方案1】:

是的。所有局部变量(在方法中定义的变量)都将位于它们自己的堆栈框架上。因此,它们将是线程安全的,前提是引用不是转义范围(方法)

注意:如果 local 引用转义了方法(作为另一个方法的参数)或方法在某些类级别或实例级别字段上起作用,那么它是 not 线程安全。

这是否意味着每个线程都会获得该方法的“副本”,即使它属于同一个实例

不,只有一种方法。每个线程共享 same 方法。但是每个线程都有自己的堆栈帧,并且局部变量将在该线程的堆栈帧上。即使您在本地对象上使用同步,逃逸分析证明 JVM 会优化您的代码并删除各种同步。

示例:

public static void main(String[] args) {

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

将有效地转换为:

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");

}

【讨论】:

【解决方案2】:

您必须将正在运行的代码正在处理的数据分开。

方法是代码,由每个线程执行。如果该代码包含诸如 int i=5 之类的语句,该语句定义了一个新变量 i,并将其值设置为 5,那么每个线程都会创建该变量。

多线程的问题不在于公共代码,而在于公共数据(和其他公共资源)。如果公共代码访问某个在别处创建的变量j,那么所有线程将访问相同的变量j,即相同的数据。如果其中一个线程在其他线程正在读取时修改共享数据,则可能会出现各种错误。

现在,关于您的问题,您的代码应该是线程安全的,只要您的变量在 bar() 中定义,并且 bar() 不会访问某些公共资源,例如文件。

【讨论】:

  • 很好的解释,谢谢。您能否分享一些相关文档的链接?
【解决方案3】:

您应该发布一些示例代码以确保我们理解用例。

对于这个例子:

public class Test {
    private String varA;

    public void doSomething() {
        String varB;

    }
}

如果你在这个例子中不做任何修改varA,只修改varB,这个例子是线程安全的。

但是,如果您创建或修改 varA 并依赖于它的状态,那么该方法是不是线程安全的。

【讨论】:

  • 感谢您的回复,但您并没有真正回答我的特定问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-13
  • 2011-05-27
相关资源
最近更新 更多