Dúvida StringBuffer [Test Killer]

Olá!

Estou com uma dúvida com relação a classe StringBuffer em um exercício do Test Killer:

O Exame TestKiller afirma que este código é Thread-Safe (Questão 89):

  1. public String toString() {
  2. StringBuffer buffer = new StringBuffer();
  3. buffer.append(?<?);
  4. buffer.append(this.name);
  5. buffer.append(?>?);
  6. return buffer.toString();
  7. }

Pelo que entendi até agora, se duas threads acessassem esse método ao mesmo o resultado poderia ser diferente do esperado e seria necessário que o método toString() fosse declarado como synchronized para que o código se tornasse Thread-safe.

E isso me deixou com essa dúvida. O código é mesmo Thread-safe?

Grato.
Paulo Gervasio

Cara eu sei que StringBuffer é Thread Safe agora não sei se por usar um objeto StringBuffer esse método viraria Thread Safe…

Não é thread-safe.

É um erro comum de quem está programando com threads imaginar que, pela classe StringBuffer ser considerada thread-safe, todas as operações com ela também serão.

O que queremos dizer com o StringBuffer ser thread-safe é que não há como duas threads chamarem o método append ao mesmo tempo, e isso corromper uma inserção no append. Agora, não há garantias de thread-safety entre duas chamadas do método append. Essa garantia você só tem quando sincroniza a classe que usa o StringBuffer.

Aliás, esse é um dos grandes motivos pelo qual ter um StringBuffer geralmente é inútil e devemos preferir o StringBuilder. Geralmente, a classe que usa o buffer terá que ser sincronizada, e isso já garante um acesso seguro ao builder.

[quote=ViniGodoy]Não é thread-safe.

É um erro comum de quem está programando com threads imaginar que, pela classe StringBuffer ser considerada thread-safe, todas as operações com ela também serão.

O que queremos dizer com o StringBuffer ser thread-safe é que não há como duas threads chamarem o método append ao mesmo tempo, e isso corromper uma inserção no append. Agora, não há garantias de thread-safety entre duas chamadas do método append. Essa garantia você só tem quando sincroniza a classe que usa o StringBuffer.

Aliás, esse é um dos grandes motivos pelo qual ter um StringBuffer geralmente é inútil e devemos preferir o StringBuilder. Geralmente, a classe que usa o buffer terá que ser sincronizada, e isso já garante um acesso seguro ao builder.[/quote]

ta explicado!! :smiley:

Legal, entendido!

Hashtable e Vector têm métodos “synchronized” e também não são muito utilizadas.

Existem outras classes padrão java que possuem métodos synchronzed?

Grato.
Paulo Gervasio.

Que eu me lembre, eram essas 3: HashTable, Vector e StringBuffer.
Todas elas foram substituídas por versões não sincronizadas: HashMap, ArrayList e StringBuilder.

Existem classes no pacote java.util.synchronized que tem sincronização, mas que justamente servem como tipos thread-safe. Como é o caso da classe AtomicInt, ou da ReentrantLock, por exemplo.

Um detalhe. Sincronização é uma das formas de se obter thread-safety, mas não a única. Classes imutáveis como String, por exemplo, são naturalmente thread-safe, mesmo sem os métodos synchronized. O uso de thread-locals para a duplicação dos dados compartilhados também pode garantir thread-safety.

Ou seja, esse assunto é um pouco mais complexo e interessante do que as certificações geralmente levam a crer.