A palavra -chave sincronizada representa que esse método está bloqueado. É equivalente a qual thread (como encadeamento A), ao executar esse método, você deve verificar se outros threads B (ou C, D, etc.) estão usando esse método (ou outros métodos de sincronização desta classe). Nesse caso, aguarde o encadeamento B (ou C, D) que está usando o método sincronizado para executar esse método antes de executar esse método. Caso contrário, bloqueie o chamador e execute -o diretamente. Inclui dois usos: o método sincronizado e o bloco sincronizado.
O mecanismo de sincronização multithread bloqueia os recursos para que, ao mesmo tempo, apenas um thread possa operar e a sincronização seja usada para resolver os problemas que podem surgir quando vários threads acessam simultaneamente.
O mecanismo de sincronização pode ser implementado usando a palavra -chave sincronizada.
Quando a palavra -chave sincronizada modifica um método, o método é chamado de método de sincronização.
Quando o método sincronizado é executado ou ocorre uma exceção, o bloqueio será liberado automaticamente.
A seguir, é apresentado um exemplo para analisar o uso de palavras -chave sincronizadas.
1. Uso diferencial de palavras -chave sincronizadas
Exemplo de programa 1
public class ThreadTest {public static void main (string [] args) {exemplo exemplo = new Exempli (); Thread t1 = new Thread1 (exemplo); Thread T2 = novo Thread1 (exemplo); t1.start (); t2.start (); }} Exemplo de classe {public sincronizado void Execute () {for (int i = 0; i <10; ++ i) {try {thread.sleep (500); } catch (interruptedException e) {e.printStackTrace (); } System.out.println ("Hello:" + i); }}} classe Thread1 estende o thread {Exemplo privado Exemplo; public Thread1 (exemplo de exemplo) {this.example = exemplo; } @Override public void run () {exemplo.execute (); }} Seja para prender a palavra -chave sincronizada no método Execute (), os resultados da execução deste programa de exemplo serão muito diferentes.
Se a palavra -chave sincronizada não for adicionada, os dois threads executam o método Execute () ao mesmo tempo e a saída será de dois grupos de concorrentes.
Se a palavra -chave sincronizada for adicionada, um conjunto de 0 a 9 será emitido primeiro e, em seguida, o próximo conjunto será emitido, indicando que os dois threads serão executados em sequência.
2. Situação de threading de vários métodos
Altere o programa e adicione outro método Execute2 () à classe Exemplo.
Em seguida, escreva um thread thread2. O método run () no thread2 executa execute2 (). Ambos os métodos na classe de exemplo são modificados pela palavra -chave sincronizada.
Exemplo de programa 2
public class ThreadTest {public static void main (string [] args) {exemplo exemplo = new Exempli (); Thread t1 = new Thread1 (exemplo); Thread t2 = new Thread2 (exemplo); t1.start (); t2.start (); }} Exemplo de classe {public sincronizado void Execute () {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (interruptedException e) {e.printStackTrace (); } System.out.println ("Hello:" + i); }} public sincronizado void Execute2 () {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (interruptedException e) {e.printStackTrace (); } System.out.println ("World:" + i); }}} classe Thread1 estende o thread {Exemplo privado Exemplo; public Thread1 (exemplo de exemplo) {this.example = exemplo; } @Override public void run () {exemplo.execute (); }} classe Thread2 estende o thread {Exemplo privado Exemplo; public Thread2 (exemplo de exemplo) {this.example = exemplo; } @Override public void run () {exemplo.execute2 (); }} Se a palavra -chave sincronizada for removida, os dois métodos serão executados simultaneamente e não terão influência mútua.
Mas, como escrito no exemplo da sub -rotina, mesmo dois métodos:
O resultado da execução é sempre a saída de um encadeamento e, em seguida, a execução de outro thread.
ilustrar:
Se um objeto possui vários métodos sincronizados e um thread inseriu um método sincronizado em um determinado momento, outros threads não poderão acessar nenhum método sincronizado do objeto antes que o método seja executado.
para concluir:
Quando a palavra -chave sincronizada modifica um método, o método é chamado de método de sincronização.
Cada objeto em Java tem um bloqueio ou um monitor. Quando um thread acessa o método sincronizado de um objeto, o objeto é bloqueado e nenhum outro encadeamento pode acessar o método sincronizado do objeto (aqui se refere a todos os métodos de sincronização, não apenas o mesmo método). Não é até o encadeamento anterior concluir o método de execução (ou lança uma exceção), a trava do objeto é liberada, para que outros threads possam acessar o método sincronizado do objeto novamente.
Observe que o objeto está bloqueado neste momento. Se for um objeto diferente, não há relação de restrição entre os objetos.
Ao tentar construir um segundo objeto de encadeamento no código, um novo objeto de exemplo é passado, não há restrição entre a execução dos dois threads.
3. Considere métodos de sincronização estática
Quando um método modificado de palavra-chave sincronizado também é modificado pela estática, foi dito antes que um método de sincronização não estático bloqueie o objeto, mas o método estático não pertence ao objeto, mas a uma classe e trava o objeto de classe da classe em que esse método está localizado.
Não importa quantos objetos uma classe gerem, eles correspondem ao mesmo objeto de classe.
Exemplo de programa 3
public class ThreadTest {public static void main (string [] args) {exemplo exemplo = new Exempli (); Thread t1 = new Thread1 (exemplo); // Mesmo que diferentes objetos sejam passados aqui, a sincronização do método estático ainda não permite que vários threads sejam executados ao mesmo tempo. Exemplo = novo exemplo (); Thread t2 = new Thread2 (exemplo); t1.start (); t2.start (); }} classe Exemplo {public sincronizado estático void Execute () {for (int i = 0; i <20; ++ i) {tente {thread.sleep ((long) math.random () * 1000); } catch (interruptedException e) {e.printStackTrace (); } System.out.println ("Hello:" + i); }} public sincronizado estático void execute2 () {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (interruptedException e) {e.printStackTrace (); } System.out.println ("World:" + i); }}} classe Thread1 estende o thread {Exemplo privado Exemplo; public Thread1 (exemplo de exemplo) {this.example = exemplo; } @Override public void run () {exemplo.execute (); }} classe Thread2 estende o thread {Exemplo privado Exemplo; public Thread2 (exemplo de exemplo) {this.example = exemplo; } @Override public void run () {exemplo.execute2 (); }} Portanto, se for um método estático (Execute () e Execute2 () ambos possuem palavras -chave estáticas adicionadas), mesmo que diferentes objetos de exemplo sejam passados para dois threads, os dois threads ainda são restringidos um pelo outro. É preciso ser executado primeiro e depois o próximo.
para concluir:
Se um método sincronizado for estático, quando um thread acessa o método, ele não bloqueia o objeto em que o método sincronizado está localizado, mas o objeto de classe correspondente à classe em que o método sincronizado está localizado. Em Java, não importa quantos objetos uma classe tenha, esses objetos corresponderão a um objeto de classe exclusivo. Portanto, quando um encadeamento acessa dois métodos estáticos e sincronizados de dois objetos da mesma classe, sua ordem de execução também é seqüencial, ou seja, um thread executa o método primeiro e o outro thread inicia após a execução ser concluída.
4. Bloco sincronizado
Método de redação de blocos sincronizados:
sincronizado (objeto) {} Isso significa que o encadeamento bloqueará o objeto quando for executado. (Observe que este objeto pode ser um objeto de qualquer classe ou você pode usar essa palavra -chave).
Dessa forma, você pode especificar o objeto bloqueado sozinho.
Exemplo de programa 4
public class ThreadTest {public static void main (string [] args) {exemplo exemplo = new Exempli (); Thread t1 = new Thread1 (exemplo); Thread t2 = new Thread2 (exemplo); t1.start (); t2.start (); }} Exemplo de classe {objeto privado objeto = new Object (); public void Execute () {sincronizado (objeto) {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (interruptedException e) {e.printStackTrace (); } System.out.println ("Hello:" + i); }}} public void Execute2 () {synchronized (object) {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (interruptedException e) {e.printStackTrace (); } System.out.println ("World:" + i); }}}}} classe Thread1 estende Thread {Exemplo privado Exemplo; public Thread1 (exemplo de exemplo) {this.example = exemplo; } @Override public void run () {exemplo.execute (); }} classe Thread2 estende o thread {Exemplo privado Exemplo; public Thread2 (exemplo de exemplo) {this.example = exemplo; } @Override public void run () {exemplo.execute2 (); }} O efeito alcançado pelo Exemplo do Programa 4 é o mesmo do programa de exemplo 2. Ambos os threads são executados em sequência, em vez de simultaneamente. Quando um thread é executado, o objeto é bloqueado e o outro thread não pode executar o bloco correspondente.
O método sincronizado é realmente equivalente a envolver todas as declarações no método com um bloco sincronizado e, em seguida, passar essa palavra -chave nos colchetes do bloco sincronizado. Obviamente, se for um método estático, o objeto de classe precisa ser bloqueado.
Talvez apenas algumas linhas de código em um método envolvam problemas de sincronização de encadeamentos; portanto, o bloco sincronizado controla o acesso de vários threads de maneira mais granular do que o método sincronizado. Somente o conteúdo no bloco sincronizado não pode ser acessado por vários threads ao mesmo tempo, e outras instruções no método ainda podem ser acessadas por vários threads ao mesmo tempo (incluindo o bloco sincronizado).
Nota: Os dados protegidos por sincronizados devem ser privados.
para concluir:
O método sincronizado é um controle simultâneo de grão grosso. Em um certo momento, apenas um thread pode executar o método sincronizado;
O bloco sincronizado é um controle de simultaneidade de granulação fina, que apenas sincroniza o código no bloco. Outros códigos localizados no método e outros blocos sincronizados podem ser acessados por vários threads ao mesmo tempo.