Se você tiver alguns métodos que não estão sincronizados e estão acessando e alterando as variáveis da instância. No seu exemplo:
private int a;
private int b;
qualquer número de threads pode acessar esses métodos não sincronizados ao mesmo tempo em que outro thread estiver no método sincronizado do mesmo objeto e pode fazer alterações nas variáveis da instância. Por exemplo: -
public void changeState() {
a++;
b++;
}
Você precisa evitar o cenário em que métodos não sincronizados estão acessando as variáveis da instância e alterando-os, caso contrário não há sentido em usar métodos sincronizados.
No cenário abaixo: -
class X {
private int a;
private int b;
public synchronized void addA(){
a++;
}
public synchronized void addB(){
b++;
}
public void changeState() {
a++;
b++;
}
}
Somente um dos encadeamentos pode estar no método addA ou addB, mas ao mesmo tempo qualquer número de encadeamentos pode inserir o método changeState. Dois threads não podem inserir addA e addB ao mesmo tempo (devido ao bloqueio no nível do objeto), mas ao mesmo tempo qualquer número de threads pode inserir changeState.
synchronized (this)
bloco ao redor do corpo do método. O objeto "this" não fica bloqueado, mas o objeto "this" é usado como o mutex e o corpo é impedido de executar simultaneamente com outras seções de código também sincronizadas em "this". Não tem efeito em outros campos / métodos "this" que não são sincronizados.