Эта переменная потока StringBuilder безопасна в этом коде? - PullRequest
2 голосов
/ 23 сентября 2010

Рассмотрим класс Action ниже, в котором я использую переменную StringBuilder внутри метода execute.Мой вопрос: является ли переменная sb поточно-безопасной или нет?

public DemoAction extends Action
{
    ......

    public ActionForward execute(.....)
    {
       StringBuilder sb = new StringBuilder();
    }
}

Что делать, если та же переменная sb объявлена ​​вне execute ().Помните, что в WebContainer будет только один объект для DemoAction .?

Ответы [ 7 ]

14 голосов
/ 23 сентября 2010

Локальные переменные являются потокобезопасными, до тех пор, пока ни один другой поток не получает ссылку на тот же экземпляр построителя строк, это потокобезопасный.

3 голосов
/ 23 сентября 2010

Это потокобезопасно, потому что вы только создаете и используете его в области действия метода, поэтому ссылка будет храниться в пространстве стека, которое является локальным для каждого потока

2 голосов
/ 23 сентября 2010

Да, локальные переменные по своей природе поточно-ориентированы.Каждый поток получает свою собственную копию.

1 голос
/ 23 сентября 2010

Из Java 6 StringBuilder Javadoc :

Этот класс предоставляет API, совместимый с StringBuffer, но без гарантии синхронизации.Этот класс предназначен для использования в качестве замены для StringBuffer в тех местах, где строковый буфер использовался одним потоком (как это обычно бывает).Там, где это возможно, рекомендуется использовать этот класс вместо StringBuffer, так как он будет быстрее в большинстве реализаций.

Это означает, что класс не является потокобезопасным, и вы должны предпочесть StringBuffer где вы знаете, что переменная будет доступна одновременно.

Однако в этом случае вы можете гарантировать, что ваш StringBuilder будет доступен только из одного потока, потому что это локальная переменная, а непеременная экземпляра.См. Вопрос «Потоковая безопасность и локальные переменные» для объяснения.

0 голосов
/ 23 сентября 2010

StringBuilder не является потокобезопасным, но пока вы используете его из одного потока, вам не нужно беспокоиться об этом. Даже если у вас есть доступ из двух потоков, вы можете легко сделать его потокобезопасным, заключив критическую секцию в синхронизированный блок, например,

private StringBuilder sb = new StringBuilder();

void appendSomething(String v) {
  synchronized (sb) {
    sb.append("You entered ");
    sb.append(v);
  }
}

Если весь метод является критическим разделом, вы можете сказать, синхронизирован по методу

synchronized void appendSomething(String v) {
 sb.append("You entered ");
 sb.append(v);
}

Примечание. Я явно написал два оператора добавления, чтобы продемонстрировать, что простое использование потокобезопасного StringBuffer не сделает код потокобезопасным. Если вы запустили два потока со StringBuffer, то каждое добавление может быть синхронизировано, но все равно будет возможно возникновение условий гонки.

private StringBuffer sb = new StringBuffer();

void appendSomething(String v) {
 sb.append("You entered ");
 // Race condition!!!
 sb.append(v);
}

Таким образом, два потока с надписью "hello" и "world" могут привести к выводу "Вы вошли Вы вошли в helloworld", потому что каждое добавление защищено не всем действием.

Использование синхронизированных классов также менее эффективно. Например, в приведенном выше примере оба вызова на добавление синхронизируются, поэтому в дополнение к условию гонки мне нужно дважды заблокировать объект по сравнению с одним разом с несинхронизированным классом.

0 голосов
/ 23 сентября 2010

Это безопасно.Эта переменная является локальной для execute() метода и создается каждый раз, когда вызывается этот метод, поэтому в многопоточной среде каждый поток может иметь свою отдельную копию переменной sb.

0 голосов
/ 23 сентября 2010

С спецификацией :

Экземпляры StringBuilder не безопасны для использования несколькими потоками.Если такая синхронизация необходима, то рекомендуется использовать StringBuffer.

Но, как Конрад Рудольф указал , в вашем случае это локальная переменная, поэтому с вами все будет в порядке

...