1. Problema síncrono levantado
A sincronização do encadeamento é para evitar danos aos dados quando vários threads acessarem um objeto de dados.
Por exemplo: ambos os threads threada e threadb operam o mesmo objeto Foo e modifique os dados no objeto Foo.
pacote cn.thread; public class Foo {private int x = 100; public int getx () {return x; } public int fix (int y) {x = x - y; retornar x; }} pacote cn.thread; public class MyRunnable implementa Runnable {private foo foo = new Foo (); public static void main (string [] args) {myRunnable run = new MyRunnable (); Thread ta = novo thread (execute, "thread-a"); Thread tb = novo thread (execute, "thread-b"); ta.start (); tb.start (); } public void run () {for (int i = 0; i <3; i ++) {this.fix (30); tente {thread.sleep (1); } catch (interruptedException e) {e.printStackTrace (); } System.out.println (thread.currentThread (). GetName () + ": o valor x do foo objeto atual =" + foo.getx ()); }} public int fix (int y) {return foo.fix (y); }}Resultados em execução:
Thread-B: o valor x do objeto Foo atual = 40
Thread-A: o valor x do objeto Foo atual = 40
Thread -B: o valor x do objeto Foo atual = -20
Thread -A: o valor X do objeto Foo atual = -20
Thread -B: o valor x do objeto Foo atual = -80
Thread -A: o valor X do objeto Foo atual = -80
A partir dos resultados, verificou -se que esse valor de saída era obviamente irracional. O motivo é que dois threads acessam objetos Foo sem controle e modificam seus dados.
Se você deseja manter a racionalidade dos resultados, só precisa atingir uma meta, que é restringir o acesso ao Foo, e apenas um thread pode acessá -lo por vez. Isso garantirá a racionalidade dos dados no objeto Foo.
No código Java específico, duas operações precisam ser concluídas:
Identifique a variável foo x da classe de recursos que é visitada pela competição como privada;
Sincronize o código que modifica as variáveis e use a palavra -chave sincronizada para sincronizar o método ou código.
pacote cn.thread; public class Foo2 {private int x = 100; public int getx () {return x; } // Método sincronizado público sincronizado int fix (int y) {x = x - y; System.out.println ("thread" + thread.currentThread (). GetName () + "Exconverce, reduza" " + y +" ", o valor atual é:" + x); retornar x; } // // Código sincronizado bloco // public int fix (int y) {// sincronizado (this) {// x = x - y; // System.out.println ("thread" + thread.currentThread (). pacote cn.thread; public class MyRunnable2 {public static void main (string [] args) {myRunnable2 run = new MyRunnable2 (); Foo2 foo2 = novo foo2 (); Mythread t1 = run.new mythread ("thread a", foo2, 10); Mythread t2 = run.new mythread ("thread b", foo2, -2); Mythread t3 = run.new mythread ("thread c", foo2, -3); Mythread t4 = run.new mythread ("thread d", foo2, 5); t1.start (); t2.start (); t3.start (); t4.start (); } classe mythread estende thread {private foo2 foo2; / ** Valor atual*/ privado int y = 0; Mythread (nome da string, foo2 foo2, int y) {super (nome); this.foo2 = foo2; this.y = y; } public void run () {foo2.fix (y); }}} Thread A Run termina, reduz "10", o valor atual é: 90
O thread c é executado e termina, reduz "-3", o valor atual é: 93
O thread B é executado no final, reduz "-2", o valor atual é: 95
O thread D funciona e termina, reduz "5", o valor atual é: 90
2. Sincronização e bloqueio
1. O princípio do bloqueio
Cada objeto em Java tem um bloqueio embutido.
Quando o programa é executado em um método de sincronização sincronizado não estático, o bloqueio associado à instância atual da classe Code está sendo executada (esta instância). Um bloqueio que adquire um objeto também é chamado de adquirir bloqueio, travar um objeto, travar um objeto ou sincronizar em um objeto.
O bloqueio do objeto funciona apenas quando o programa é executado para um método de sincronização sincronizado ou bloco de código.
Existe apenas um bloqueio para um objeto. Portanto, se um thread adquirir a trava, nenhum outro encadeamento poderá adquirir a trava até que o primeiro thread libere (ou retorne) o bloqueio. Isso também significa que nenhum outro encadeamento pode entrar no método sincronizado ou bloco de código no objeto até que o bloqueio seja liberado.
A liberação de um bloqueio significa que o encadeamento de bloqueio sai do método de sincronização sincronizado ou bloco de código.
Existem alguns pontos -chave sobre bloqueio e sincronização:
1) Somente métodos podem ser sincronizados, mas variáveis e classes não podem ser sincronizadas;
2) Cada objeto tem apenas um bloqueio; Quando se trata de sincronização, o que deve ser claro? Isto é, em qual objeto é sincronizado?
3) Não há necessidade de sincronizar todos os métodos da classe. As classes podem ter métodos síncronos e assíncronos.
4) Se dois threads quiserem executar o método sincronizado em uma classe e os dois threads usarem a mesma instância para chamar o método, apenas um thread poderá executar o método de cada vez e o outro precisará esperar até que a fechadura seja liberada. Ou seja: se um thread adquirir um bloqueio em um objeto, nenhum outro thread poderá inserir qualquer método de sincronização na classe (desse objeto).
5) Se o encadeamento possui métodos de sincronização e assíncrono, os métodos assíncronos poderão ser acessados livremente por vários threads sem serem restritos por bloqueios.
6) Quando o thread dorme, nenhuma bloqueio que ele se mantém será liberada.
7) Os threads podem obter vários bloqueios. Por exemplo, chamar o método de sincronização de outro objeto no método de sincronização de um objeto adquirirá a trava de sincronização dos dois objetos.
8) A sincronização prejudica a simultaneidade e deve restringir a faixa de sincronização o máximo possível. A sincronização pode não apenas sincronizar todo o método, mas também sincronizar alguns blocos de código no método.
9) Ao usar blocos de código de sincronização, você deve especificar qual objeto sincronizar, ou seja, qual bloqueio do objeto deve ser adquirido. Por exemplo:
public int fix (int y) {sincronizado (this) {x = x - y; } retornar x;} Obviamente, o método de sincronização também pode ser reescrito como um método assíncrono, mas as funções são exatamente as mesmas, por exemplo:
public sincronizado int getx () {return x ++;} e
public int getx () {sincronizado (this) {return x ++; }}O efeito é exatamente o mesmo.
3. Sincronização do método estático
Para sincronizar métodos estáticos, é necessário um bloqueio para todo o objeto de classe, que é essa classe (xxx.class).
Por exemplo:
public static sincronizado int setName (nome da string) {xxx.name = name;}
Equivalente a
public static int setName (nome da string) {synchronized (xxx.class) {xxx.name = name; }}4. O que acontece se o fio não puder obter a fechadura
Se o thread tentar inserir um método síncrono e seu bloqueio estiver ocupado, o thread será bloqueado no objeto. Essencialmente, um thread entra em um pool do objeto e deve esperar onde ele deve esperar até que sua trava seja liberada e o thread se torne correável ou executado novamente.
Ao considerar o bloqueio, não se esqueça de prestar atenção a qual objeto está sendo usado para travar:
1. Os encadeamentos que chamam métodos de sincronização não estática no mesmo objeto se bloquearão. Se for um objeto diferente, cada thread possui seu próprio bloqueio de objeto e os threads não interferem entre si.
2. Os threads que chamam métodos de sincronização estática na mesma classe se bloqueam e todos estão bloqueados no mesmo objeto de classe.
3. Métodos de sincronização estática e métodos de sincronização não estática nunca se bloquearão, porque os métodos estáticos são bloqueados em objetos de classe, enquanto os métodos não estáticos são bloqueados nos objetos dessa classe.
4. Para blocos de código sincronizado, você precisa ver claramente quais objetos foram usados para travar (o conteúdo dos colchetes sincronizados após sincronizado). Os threads sincronizados no mesmo objeto se bloquearão e os threads bloqueados em diferentes objetos nunca se bloquearão.
5. Quando é a necessidade de sincronizar
Quando vários threads acessam dados mutuamente exclusivos (trocáveis) simultaneamente, eles devem ser sincronizados para proteger os dados, garantindo que ambos os threads não o modifiquem e alterem -os ao mesmo tempo.
Para dados que podem ser alterados em campos não estáticos, os métodos não estáticos geralmente são acessados.
Para dados que podem ser alterados em um campo estático, geralmente são acessados usando um método estático.
O problema se torna muito complicado se você precisar usar campos estáticos em métodos não estáticos ou chamar métodos não estáticos em campos estáticos. Ele excedeu o escopo do exame SJCP.
6. Categoria de segurança de thread
Quando uma classe é bem sincronizada para proteger seus dados, essa classe é chamada de "segura para threads".
Mesmo para aulas seguras de threads, você deve ter muito cuidado, porque os threads que operam ainda não são necessariamente seguros.
7. Resumo da sincronização de threads
1. O objetivo da sincronização do encadeamento é proteger os danos aos recursos quando vários threads acessarem um recurso.
2. O método de sincronização do thread é implementado através de bloqueios. Cada objeto tem apenas um bloqueio. Este bloqueio está associado a um objeto específico. Depois que o encadeamento adquire o bloqueio do objeto, outros threads que acessam o objeto não podem mais acessar outros métodos de sincronização do objeto.
3. Para métodos de sincronização estática, os bloqueios são para esta classe e os objetos de trava são objetos de classe dessa classe. Os bloqueios de métodos estáticos e não estáticos não interferem entre si. Um encadeamento adquire um bloqueio e, ao acessar um método de sincronização em outro objeto em um método de sincronização, adquire esses dois bloqueios de objetos.
4. Para sincronização, é essencial estar sempre ciente de qual objeto se sincronizar.
5. Ao escrever classes seguras de threads, você precisa sempre prestar atenção em fazer julgamentos corretos sobre a lógica e a segurança de vários threads competindo para acessar recursos, analisar as operações "atômicas" e garantir que outros threads não possam acessar os recursos concorrentes durante a operação atômica.
6. Quando vários threads aguardam uma trava de objeto, o encadeamento que não obteve o bloqueio será bloqueado.
7. O impasse é causado por fios que se aguardam travar um ao outro, e a probabilidade de ocorrência na realidade é muito pequena. Se você realmente deseja escrever um programa de impasse, pode não ser fácil, haha. No entanto, uma vez que um programa morre, o programa morrerá.
Link original: http://www.cnblogs.com/linjiqin/p/3208843.html
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.