O código a seguir demonstra como sincronizar métodos de classe específicos:
Copie o código do código da seguinte forma:
pacote mitoread;
classe pública SyncThread estende Thread
{
private static String sincronização = "";
private String metodoType = "";
método void estático privado (String s)
{
sincronizado (sincronizar)
{
sincronização = s;
System.out.println(s);
enquanto (verdadeiro);
}
}
método de vazio público1()
{
método("método1");
}
público estático void staticMethod1()
{
método("Metodoestático1");
}
execução de vazio público ()
{
if (methodType.equals("estático"))
staticMethod1();
senão if (methodType.equals("não estático"))
método1();
}
SyncThread público (String methodType)
{
this.methodType = métodoType;
}
public static void main(String[] args) lança exceção
{
SyncThread sample1 = new SyncThread("não estático");
SyncThread amostra2 = new SyncThread("estático");
amostra1.start();
amostra2.start();
}
}
Os resultados da execução são os seguintes:
Copie o código do código da seguinte forma:
método1
método estático1
Muitos leitores podem ficar surpresos ao ver os resultados acima. No código acima, os métodos method1 e staticMethod1 usam a variável de string estática sync para sincronização. Apenas um desses dois métodos pode ser executado ao mesmo tempo, e ambos os métodos executarão a instrução de loop infinito na linha 014. Portanto, o resultado de saída pode ser apenas um entre method1 e staticMethod1. Mas este programa produz ambas as strings.
A razão para este resultado é muito simples, saberemos olhando a linha 012. Acontece que o valor de sincronização é alterado nesta linha. Aqui quero falar sobre o tipo String em Java. O tipo String é diferente de outros tipos complexos em Java. Ao usar uma variável do tipo String, contanto que você atribua um valor à variável uma vez, Java criará uma nova instância do tipo String. Conforme mostrado no código a seguir:
Copie o código do código da seguinte forma:
Strings = "olá";
System.out.println(s.hashCode());
s = “mundo”;
System.out.println(s.hashCode());
no código acima. Os valores hashCode dos primeiros s e dos s reatribuídos são diferentes. Como a criação de uma instância da classe String não requer o uso de new, ao sincronizar uma variável do tipo String, tome cuidado para não atribuir um valor a esta variável, caso contrário a variável não será sincronizada.
Como uma nova instância para sincronização foi criada na linha 012, supondo que o método1 seja executado primeiro, quando o método1 executa o código na linha 013, o valor de sincronização não é mais o valor original e o método1 ainda bloqueia a variável de sincronização. . Neste momento, staticMethod1 é executado para sincronizado (sync). A sincronização a ser bloqueada no método staticMethod1 e a sincronização bloqueada pelo método method1 não são mais iguais.
A solução para o problema acima é, obviamente, remover a linha 012. Esta linha é adicionada a este exemplo apenas para ilustrar que ao usar variáveis de classe para sincronizar métodos, se o valor da variável de sincronização for alterado no bloco sincronizado, a sincronização entre os métodos será destruída. Para evitar completamente esta situação, você pode usar a palavra-chave final ao definir variáveis de sincronização. Por exemplo, a linha 005 do programa acima pode ser alterada para o seguinte formato:
Copie o código do código da seguinte forma:
private final static String sync = "";
Depois de usar a palavra-chave final, a sincronização só pode atribuir um valor a ela quando for definida e não pode ser modificada posteriormente. Se à sincronização for atribuído um valor em outro lugar do programa, o programa não será compilado. Em ferramentas de desenvolvimento como o Eclipse, os prompts serão fornecidos diretamente no lugar errado.
Podemos entender os blocos sincronizados de duas perspectivas. Se entendido da perspectiva dos métodos de classe, os métodos correspondentes podem ser sincronizados através de variáveis de classe. Se você entender isso da perspectiva das variáveis de classe, poderá usar blocos sincronizados para garantir que uma variável de classe só possa ser acessada por um método ao mesmo tempo. Não importa de que ângulo você entenda, sua essência é a mesma, que é usar variáveis de classe para obter bloqueios de sincronização e alcançar a sincronização por meio da exclusão mútua de bloqueios de sincronização.
Nota: Ao usar blocos sincronizados, você deve estar ciente de que os blocos sincronizados só podem usar objetos como parâmetros. Se for um tipo simples de variável (como int, char, boolean, etc.), sincronizado não poderá ser usado para sincronização.