【问题标题】:How to set/get string in Java safely?如何安全地在 Java 中设置/获取字符串?
【发布时间】:2011-12-28 03:33:57
【问题描述】:

我读过 Java String 类是不可变的和线程安全的,但我仍然对字符串的引用分配是否是线程安全的感到困惑。

第一个问题:如果线程A调用Foo.setString()而线程B调用Foo.getString(),下面的代码是线程安全的吗?

Class Foo {
    String aString;
    public String getString() {
        return aString;
    }
    public void setString(s) {
        aString = s;
    }
}

第二个问题:如果上面的代码不是线程安全的,使用了ReentrantLock,我该如何写Foo.getString()方法?

Class Foo {
    String aString;
    ReentrantLock aLock;
    public String getString() {
        aLock.lock();
        return aString;
        aLock.unlock(); // This line will be unreachable. How to fix??
    }
    public void setString(s) {
        aLock.lock();
        aString = s;
        aLock.unlock();
    }
}

我必须使用 ReentrantLock,因为我需要使用 tryLock(timeout) 功能。

【问题讨论】:

  • 如果我的两个问题都得到了回答,将接受答案。谢谢。

标签: java string thread-safety immutability reentrantlock


【解决方案1】:

问题 1: 这取决于你所说的线程安全,Eric Lippert wrote a very good blog post about it here... 但是将 aString 声明为 volatile 将意味着不同线程上的任何读取都保证是正确的。

问题 2:

使用 try... finally 构造,在 finally 块中解锁例如:

public String getString() {
  try {        
    aLock.lock();
    return aString;
  } finally {
    aLock.unlock();
  }
}

public void setString(s) {
  try {        
    aLock.lock();
    aString = s;
  } finally {
    aLock.unlock();
  }
}

【讨论】:

  • 也很想了解我的第一个问题。
【解决方案2】:

使用synchronized关键字:

   public synchronized String getString() {
        return aString;
    }

    public synchronized void setString(s) {
        aString = s;
    }

【讨论】:

  • 抱歉,我必须使用 ReentrantLock,因为我需要使用 tryLock(timeout) 功能。
  • 好的,没注意到。所以最好像其他海报建议的那样在 finally 块中解锁。
  • 为什么需要使用tryLock?这是作业还是类似的?
【解决方案3】:

在这种情况下,您只需要使aString volatile 成为您所需要的(即,在写入后读取将始终看到最新值) - 使方法同步并不是特别有用,因为我们只执行单个语句 - 在这两种情况,所以如果你想做更多的工作,无论如何你都需要更高级别的同步(比如“如果字符串是 XYZ,那么将 XYA 分配给它”)。 IE。 synchronized 和 volatile 都为您提供了相同的保证(除了我们在类的其他地方使用 synchronized 时的明显区别)

所以 volatile 就足够了,而且性能更高,但同步也一样好 - 您可以注意到的唯一性能差异是如果您有很多竞争访问,但否则没关系 - 同步针对非竞争访问进行了极大优化至少在 Hotspot 上(但我认为所有现代 JVM 都是如此)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-09
    • 2020-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多