Sincronização em “this” ou object privado em Java?

Duplicar Possível:
Evite sincronizado (isso) em Java?

Qual é a diferença entre os dois pedaços de código? Quais são as vantagens e desvantagens de cada um?

1)

public class Example { private int value = 0; public int getNextValue() { synchronized (this) { return value++; } } } 

2)

 public class Example { private final Object lock = new Object(); private int value = 0; public int getNextValue() { synchronized (lock) { return value++; } } } 

A principal razão pela qual eu escolheria a segunda abordagem é que eu não controle o que os clientes fazem com as instâncias da minha class.

Se, por algum motivo, alguém decidir usar uma instância da minha class como bloqueio, ela interferirá na lógica de synchronization da minha class:

 class ClientCode { Example exampleInstance; void someMethod() { synchronized (exampleInstance) { //... } } } 

Se, dentro da minha class Example , eu estiver usando um bloqueio que ninguém mais pode ver, eles não podem interferir na minha lógica e introduzir um mutex arbitrário como no cenário acima.

Em suma, esta é apenas uma aplicação do princípio de ocultação de informações.

Eu preferiria a segunda opção se eu precisasse executar duas tarefas diferentes simultaneamente, independentes umas das outras.

por exemplo:

 public class Example { private int value = 0; private int new_value = 0; private final Object lock1 = new Object(); private final Object lock2 = new Object(); public int getNextValue() { synchronized (lock1) { return value++; } } public int getNextNewValue() { synchronized (lock2) { return new_value++; } } } 

Eu diria que o segundo método é melhor. Considere a seguinte situação:

 public class Abc{ private int someVariable; public class Xyz { //some method,synchronize on this } //some method, and again synchronize on this } 

Nesta situação, this não é o mesmo nos dois methods. Um é um método da class interna. Portanto, é melhor usar um object comum para synchronization. Por exemplo, synchronized (someVariable) .

Eu acho que realmente depende da situação. Vamos dizer que sua class é uma subclass e a superclass tem um método que tem synchronization. E digamos que você esteja trabalhando com o mesmo dataset e queira manter a integridade em seu método também. Então definitivamente abordagem 1 é o que você deveria estar usando.

Caso contrário, a segunda abordagem funcionaria melhor com base no que Costi mencionou