【问题标题】:Java: Thread safety with StringBuilderJava:使用 StringBuilder 实现线程安全
【发布时间】:2013-05-30 21:57:12
【问题描述】:

我有一个场景,我想在方法中使用StringBuilder 作为局部变量。我知道如果StringBuilder 是一个局部方法变量,它不应该有任何线程安全问题。

但是,如果我在 StringBuilder 上附加一个实例变量,例如:

class MyClass {
    private List<String> property;

    public void myMethod() {
        StringBuilder sb = new StringBuilder();
        for(String s : property) {
            sb.append(s);
        }
    }

    // some other methods that mutate property
}

我认为要使这个线程安全,只需将StringBuilder 更改为StringBuffer 是不够的。我应该在属性本身上进行同步吗?

【问题讨论】:

标签: java multithreading thread-safety stringbuilder


【解决方案1】:

危险的不是StringBuilder,而是List&lt;String&gt; property。你有两个选择:

  1. 制作myMethod和其他改变属性synchronized的方法

  2. 使用java.util.concurrent.CopyOnWriteArrayList,它是线程安全的并为迭代器制作快照

【讨论】:

  • 仅供 OP 参考:如果您打算进行大量更新,请注意 CopyOnWriteArrayList 方法;在这种情况下,您最好选择选项 1。
【解决方案2】:

似乎同步问题出在属性上。

所以只需在其上添加一个同步:

synchronized (property) {
   ...
}

【讨论】:

    【解决方案3】:

    您可以在property 或任何对象上进行同步,只要您在访问property 的任何位置的相同 对象上进行同步。

    同步的替代方法是使用List 的线程安全实现,例如CopyOnWriteArrayList,如果经常读取列表但不经常修改,这很好(速度快,争用比同步少)。

    【讨论】:

      【解决方案4】:

      问题在于,当您调用您的myMethod() 时,另一个线程可以将新的String 添加到您的property 列表中,从而修改结果。

      避免这种情况的一种方法是在以任何方式访问属性的方法中使用synchronized,或者您可以使用旧的ReadWriteLock。最常用的实现是ReentrantReadWriteLock。互联网上有很好的例子,但你会做的是:

      class MyClass {
          private final ReadWriteLock propertiesLock = new ReentrantReadWriteLock();
          private final Lock read = propertiesLock.readLock();
          private final Lock write = propertiesLock.writeLock();
          ... 
      
          public StringBuilder myMethod() {
              StringBuilder builder = new StringBuilder();
              read.lock();
              try {
                 // your writing here.
              } finally {
                  read.unlock();
              }
              return builder;
          }
      
          public void addProperty(String property) {
              write.lock();
              try {
                  properties.add(property);
              } finally {
                  write.unlock();
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2010-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多