Assim, quando colocamos um método em synchronized dizemos que ele é "travável" para aquela instância daquela classe como um todo (this). Um código semelhante ao abaixo:
//Classe ProduzMensagens
public synchronized void run() {
for(int i = comeco; i < fim; i++) {
mensagens.add("Mensagem " + i);
}
}
Aí em nossa classe de testes fazemos isso:
Thread t1 = new Thread(new ProduzMensagens(0, 10000, mensagens));
Thread t2 = new Thread(new ProduzMensagens(10000, 20000, mensagens));
Thread t3 = new Thread(new ProduzMensagens(20000, 30000, mensagens));
Criamos três instâncias da classe ProduzMensagens, passando cada uma como argumento numa thread diferente.
Nesse caso a palavra reservada synchronized é inútil; o resultado é o mesmo se não a usarmos. Porque há três instâncias diferentes de ProduzMensagens, cada uma com seu método run. Porque a synchronized "trava" o método para aquela instância (essa última frase é a minha dúvida).
Esse exemplo apenas faria sentido se todas as threads recebessem como argumento uma mesma instância de ProduzMensagens. Para resolver isso passo o lock do objeto mensagens,de modo que a instancia daquele objeto e não da classe que possuí o método seja "travável" e controlado por uma thread por vez:
public void run() {
for(int i = comeco; i < fim; i++) {
synchronized(mensagens) {
mensagens.add("Mensagem " + i);
}
}
}
Entendeu meu raciocínio? Queria saber se é isso mesmo...