【问题标题】:Thread and mutable params线程和可变参数
【发布时间】:2014-01-08 15:21:25
【问题描述】:

我是 Java 新手,如果以下简单案例的答案很明显,请原谅。

class A{
   public void foo(Customer cust){
       cust.setName(cust.getFirstName() + " " + cust.getLastName());
       cust.setAddress(new Address("Rome"));
   }
}

我为 A 类创建了一个单例对象 (objectA)。

  1. 鉴于我没有任何类变量,如果我从不同线程调用 objectA.foo(new Customer()) 是否线程安全?

  2. 如果我将 foo 更改为 static 并从不同的线程调用 A.foo(new Customer()) 会怎样? 它仍然是线程安全的吗?

【问题讨论】:

  • 使方法synchronized 不会自动使其成为线程安全的。事实上,在这个例子中,它不会做任何有用的事情。

标签: java multithreading thread-safety


【解决方案1】:

鉴于我没有任何类变量,如果我调用它是否是线程安全的 来自不同线程的 objectA.foo(new Customer())?

当然是。您的foo() 方法不会更改A 对象的任何状态(因为它没有任何状态)并且您传递的对象new Customer() 作为该方法的参数对任何其他线程都不可用。

如果我将 foo 更改为 static 并调用 A.foo(new Customer()) 从 不同的线程?它仍然是线程安全的吗?

只要你没有任何可变的static 状态,你仍然很好。

【讨论】:

  • 可能投反对票的人不理解您的答案。
  • 感谢您的回答,我问这个问题的前提是,stackoverflow.com/a/18547670/388889,不确定它有多准确。但它说“如果你在 o 参数中传递的每个对象都是不可变的”,这里的 Customer 不是不可变的。有什么提示吗?
  • @Aymer 这里的关键字是共享可变数据。如果对象不在各个线程之间共享,那么尽管它是可变的,但它仍然是线程安全的
  • @Aymer 因为您直接在方法调用中创建对象 (new Customer()),所以对它的引用不可能泄漏到任何其他线程。
  • @SotiriosDelimanolis & John,感谢您的澄清。顺便说一句,没想到会有这么快的反应!
【解决方案2】:

是的,这将是线程安全的 IF 您从不同的线程调用 foo(new Customer())。但这只是因为每次调用new Customer() 时,您都在创建一个新的(因此不同的)客户对象,而 foo 所做的只是改变传递给它的客户的状态。因此这些线程不会发生冲突,因为即使它们调用相同的方法,它们也会操纵不同的客户。

但是,如果您要先创建客户变量 p>

Customer bob = new Customer()

然后从两个不同的线程调用foo(bob),这不是线程安全的。第一个线程可能正在更改地址,而第二个线程正在更改名称,从而导致行为不一致和/或数据损坏。

如果你想让这个方法真正线程安全,只需声明方法同步:

public synchronized void foo(Customer cust) {...}

【讨论】:

  • 感谢您的回复。
【解决方案3】:

函数访问静态共享变量时需要线程安全。就像一个正在更新共享文档的函数,所以如果两个线程并行更新一个线程的更改将被忽略。或跨应用程序共享的静态变量,单例对象。

以上是一些需要线程安全的情况在您的情况下,您没有更新任何共享资源,因此这是线程安全的。

【讨论】:

    猜你喜欢
    • 2010-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    相关资源
    最近更新 更多