Duas formas de como colocar um método Thread-Safe?
Segue as minhas sugestões…abraço
1-)public void synchronized meuMetodo(){}
2-)public void meuMetodo(){
synchronized( objectMonitor ){
}
}
1-Neste caso o sincronização seria baseado no objeto utilizado para chamar este método
2-Neste caso a sincronização seria baseado no objeto fornecido ao bloco synchronized, fornecendo uma maior flexibilidade em relação á primeira opção.
Na verdade, para que um método seja thread safe ele não precisa necessariamente ser sincronizado. Basta que se use objetos imutáveis (como Strings) ou que só se faça leitura sobre os dados. Ou, ainda, que os dados sejam criados dentro do método (objetos criados dentro do escopo de um método não são compartilhados entre threads).
[]'s
asaudate
poderia dar um exemplo de código que use objetos imutáveis?
[quote=Gianetti]asaudate
poderia dar um exemplo de código que use objetos imutáveis?[/quote]
Exemplos tem vários… por exemplo:
public class Teste {
private BigDecimal valorQualquer = new BigDecimal("10.0");
public void fazAlgoPotencialmentePerigoso() {
valorQualquer.add(new BigDecimal("20.0"));
System.out.println(valorQualquer);
}
}
Desafio: sabe o que esse código imprime? Isso mesmo, 10. Porque BigDecimal é imutável. Para ele funcionar, o add teria que ter como resultado algum BigDecimal (que não fosse o próprio valorQualquer, porque nesse caso, o método deixaria de ser thread safe).
Trocando em míudos, fazer o seguinte:
public class Teste {
private BigDecimal valorQualquer = new BigDecimal("10.0");
public void fazAlgoPotencialmentePerigoso() {
BigDecimal resultado = valorQualquer.add(new BigDecimal("20.0"));
System.out.println(resultado);
}
}
Não teria qualquer impacto num ambiente multithread, porque BigDecimal é imutável. Para construir uma classe imutável, tem uma série de regras que devem ser seguidas. Uma é transformar a classe em final. Outra, é não ter setters (e, se tiver, que eles retornem outra instância do mesmo tipo - como no caso do BigDecimal).
[]'s
show de bola a explicação obrigado.
Métodos são thread-safe se:
- Usarem somente parâmetros primitivos, variáveis locais, ou ThreadLocals;
- Tiverem todas as variáveis compartilhadas com outros métodos dentro de trechos sincronizados com o mesmo lock, em todos os locais que essas variaveis aparecem.
- Realizarem apenas uma única operação atômica, sobre uma variável que seja declarada como volatile, ou que sejam objetos do java.util.concurrent.Atomic (como o AtomicInteger, por exemplo);
- Forem métodos de um objeto imutável. Objetos imutáveis são naturalmente thread-safe e não necessitam de sincronização.
Será que esqueci de algum caso?
Existem boas alternativas para garantir thread-safety, sem necessariamente ter uma classe thread-safe.
- Criar um mecanismo de produtor/consumidor. Assim você terá threads comunicando-se por mensagens, e as classes dentro dessas threads acessados só pela thread que recebe as mensagens (e, portanto, elas não precisarão ser thread-safe). Você só precisa garantir thread-safety na fila de mensagens, e no java já há classes para essas filas prontas.
- Criar cópias de objetos, por thread (o ThreadLocal ajuda nessa tarefa);
Muitas vezes, essas alternativas garantem mais parelelismo do que se você tentar usar sincronização.
Finalmente, atributos static mutáveis, se colocados em regiões críticas, são a pior coisa possível em aplicações multi-thread. Por serem static eles geralmente só podem ser acessados por uma thread por vez.
Excelente explicação, muito bom conhecer os demais aspectos do Thread - Safe