Bom, ainda não consegui assimilar qual a função da palavra reservada “sincronized” em métodos java. Se algum puder me explicar eu agradeço.
Esse modificador não referente a acesso, assegura que um método ou bloco de código seja acessado por uma Thread de cada vez.
É possível sincronizar tanto métodos static, quanto não-static. Não é possível utiliza-la em atributos ou classes.
Enquanto a Thread estiver percorrendo o trecho sincronizado, ela bloqueia no objeto, isso no caso de trechos não static, o bloqueio eh liberado quando a Thread encerra sua tarefa dentro do trecho sincronizado ou por meio de notificações do objeto, fazendo com que uma Thread que esteja aguardando no pool, independente da sua prioridade, seja escolhida para ser executada.
Existem diversos exemplos acerca do assunto, por exemplo: http://www.guj.com.br/java/115537-synchronized-em-thread
Espero ter ajudado, qualquer coisa, avisa.
[]'s
Legal, ótima explicação. Aproveitando a deixa, gostaria de entender porque o código abaixo (implementando Runnable) está executando sequencialmente a minha resposta:
package br.com.socic.recargacelular.importacao.bo;
public class MyTestSincronized {
public static void main(String[] args) {
new Thread(t1).start();
new Thread(t2).start();
}
private static void countMe(String name, int i){
System.out.println("Current Counter is: " + i + ", updated by: " + name);
}
private static Runnable t1 = new Runnable() {
public void run() {
try{
for(int i=1; i<=100; i++){
countMe("t1",i);
}
} catch (Exception e){}
}
};
private static Runnable t2 = new Runnable() {
public void run() {
try{
for(int i=1; i<=100; i++){
countMe("t2",i);
}
} catch (Exception e){}
}
};
}
Resposta:
Current Counter is: 1, updated by: t1
Current Counter is: 2, updated by: t1
Current Counter is: 3, updated by: t1
Current Counter is: 4, updated by: t1
Current Counter is: 5, updated by: t1
Current Counter is: 6, updated by: t1
Current Counter is: 7, updated by: t1
Current Counter is: 8, updated by: t1
Current Counter is: 9, updated by: t1
Current Counter is: 10, updated by: t1
Current Counter is: 11, updated by: t1
Current Counter is: 12, updated by: t1
Current Counter is: 13, updated by: t1
Current Counter is: 14, updated by: t1
Current Counter is: 15, updated by: t1
Current Counter is: 1, updated by: t2
Current Counter is: 2, updated by: t2
Current Counter is: 3, updated by: t2
Current Counter is: 4, updated by: t2
Current Counter is: 5, updated by: t2
Current Counter is: 6, updated by: t2
Current Counter is: 7, updated by: t2
Current Counter is: 8, updated by: t2
Current Counter is: 9, updated by: t2
Current Counter is: 10, updated by: t2
Current Counter is: 11, updated by: t2
Current Counter is: 12, updated by: t2
Current Counter is: 13, updated by: t2
Current Counter is: 14, updated by: t2
Current Counter is: 15, updated by: t2
Não deveria ficar tudo misturado já que ele executa 1 depois executa outro e assim por diante ?
Existe a máxima de que quando o assunto eh Threads não se pode assegurar o resultado, existem formas de influencia-las, apenas.
Por exemplo, eu acabei de executar o seu código na minha máquina e o resultado foi o seguinte:
Current Counter is: 1, updated by: t1
Current Counter is: 1, updated by: t2
Current Counter is: 2, updated by: t2
Current Counter is: 3, updated by: t2
Current Counter is: 4, updated by: t2
Current Counter is: 5, updated by: t2
Current Counter is: 6, updated by: t2
Current Counter is: 7, updated by: t2
Current Counter is: 8, updated by: t2
Current Counter is: 9, updated by: t2
Current Counter is: 10, updated by: t2
Current Counter is: 11, updated by: t2
Current Counter is: 12, updated by: t2
Current Counter is: 13, updated by: t2
Current Counter is: 14, updated by: t2
Current Counter is: 15, updated by: t2
Current Counter is: 16, updated by: t2
Current Counter is: 17, updated by: t2
Current Counter is: 18, updated by: t2
Current Counter is: 19, updated by: t2
Current Counter is: 2, updated by: t1
Current Counter is: 3, updated by: t1
Current Counter is: 4, updated by: t1
Current Counter is: 5, updated by: t1
Current Counter is: 6, updated by: t1
Current Counter is: 7, updated by: t1
Current Counter is: 8, updated by: t1
Current Counter is: 9, updated by: t1
[]'s
Quando digo resultado, eu me refiro a sequencia em que as Threads serão executadas.
A unica garantia que nós temos eh a seguinte, elas serão iniciadas e concluidas, agora, não cabe ao programador precisar isso, eh de acordo com a implementação da JVM, segundo a especificação.
Como eu disse, o que pode ser feito eh influencia-la, fazer por exemplo, com que um Thread não percorra o código depressa demais.
O seu código executado outra vez:
Current Counter is: 1, updated by: t2
Current Counter is: 2, updated by: t2
Current Counter is: 3, updated by: t2
Current Counter is: 4, updated by: t2
Current Counter is: 5, updated by: t2
Current Counter is: 6, updated by: t2
Current Counter is: 7, updated by: t2
Current Counter is: 8, updated by: t2
Current Counter is: 9, updated by: t2
Current Counter is: 10, updated by: t2
Current Counter is: 11, updated by: t2
Current Counter is: 12, updated by: t2
Current Counter is: 13, updated by: t2
Current Counter is: 14, updated by: t2
Current Counter is: 1, updated by: t1
Current Counter is: 2, updated by: t1
Current Counter is: 3, updated by: t1
Current Counter is: 4, updated by: t1
Current Counter is: 5, updated by: t1
Current Counter is: 6, updated by: t1
Current Counter is: 7, updated by: t1
Current Counter is: 8, updated by: t1
Current Counter is: 9, updated by: t1
Current Counter is: 10, updated by: t1
Current Counter is: 11, updated by: t1
Current Counter is: 12, updated by: t1
Current Counter is: 13, updated by: t1
[]'s
Se eu adicionasse sinchronized ao metodo countMe qual seria o provavel resultado?
Nesse exemplo, cada Thread tem o seu trabalho a ser feito, eu modifiquei o seu código para tentar exemplificar. Eu dei nome as duas Threads, entretanto, as duas executam o mesmo alvo:
[code]public class MyTestSincronized {
public static void main(String[] args) {
Thread a = new Thread(t1);
Thread b = new Thread(t1);
a.setName("getAdicted");
b.setName("rlanhellas");
a.start();
b.start();
}
private static void countMe(String name, int i){
System.out.println(Thread.currentThread().getName() +" Current Counter is: " + i + ", updated by: " + name);
}
private static Runnable t1 = new Runnable() {
public void run() {
try{
for(int i=1; i<=100; i++){
countMe("t1",i);
}
} catch (Exception e){}
}
};
}[/code]
Saida:
getAdicted Current Counter is: 9, updated by: t1
getAdicted Current Counter is: 10, updated by: t1
getAdicted Current Counter is: 11, updated by: t1
getAdicted Current Counter is: 12, updated by: t1
getAdicted Current Counter is: 13, updated by: t1
getAdicted Current Counter is: 14, updated by: t1
getAdicted Current Counter is: 15, updated by: t1
getAdicted Current Counter is: 16, updated by: t1
getAdicted Current Counter is: 17, updated by: t1
getAdicted Current Counter is: 18, updated by: t1
getAdicted Current Counter is: 19, updated by: t1
rlanhellas Current Counter is: 1, updated by: t1
rlanhellas Current Counter is: 2, updated by: t1
rlanhellas Current Counter is: 3, updated by: t1
rlanhellas Current Counter is: 4, updated by: t1
rlanhellas Current Counter is: 5, updated by: t1
rlanhellas Current Counter is: 6, updated by: t1
rlanhellas Current Counter is: 7, updated by: t1
rlanhellas Current Counter is: 8, updated by: t1
rlanhellas Current Counter is: 9, updated by: t1
rlanhellas Current Counter is: 10, updated by: t1
rlanhellas Current Counter is: 11, updated by: t1
Saida, acrescentando synchronized:
private static synchronized void countMe(String name, int i){
System.out.println(Thread.currentThread().getName() +" Current Counter is: " + i + ", updated by: " + name);
}
...
getAdicted Current Counter is: 89, updated by: t1
getAdicted Current Counter is: 90, updated by: t1
getAdicted Current Counter is: 91, updated by: t1
getAdicted Current Counter is: 92, updated by: t1
getAdicted Current Counter is: 93, updated by: t1
getAdicted Current Counter is: 94, updated by: t1
getAdicted Current Counter is: 95, updated by: t1
getAdicted Current Counter is: 96, updated by: t1
getAdicted Current Counter is: 97, updated by: t1
getAdicted Current Counter is: 98, updated by: t1
getAdicted Current Counter is: 99, updated by: t1
getAdicted Current Counter is: 100, updated by: t1
rlanhellas Current Counter is: 1, updated by: t1
rlanhellas Current Counter is: 2, updated by: t1
rlanhellas Current Counter is: 3, updated by: t1
rlanhellas Current Counter is: 4, updated by: t1
rlanhellas Current Counter is: 5, updated by: t1
rlanhellas Current Counter is: 6, updated by: t1
rlanhellas Current Counter is: 7, updated by: t1
rlanhellas Current Counter is: 8, updated by: t1
rlanhellas Current Counter is: 9, updated by: t1
rlanhellas Current Counter is: 10, updated by: t1
rlanhellas Current Counter is: 11, updated by: t1
rlanhellas Current Counter is: 12, updated by: t1
rlanhellas Current Counter is: 13, updated by: t1
...
Repare que enquanto a Thread a obteve o bloqueio, ela executou o trabalho até o fim.
[]'s
Uma correção, sincronizar o método countMe nao eh o bastante, mais apropriado eh deixar a implementação do for dentro do método countMe.
Eu não procurei alterar muito o seu código:
[code] private static Runnable t1 = new Runnable() {
public void run() {
try{
synchronized (t1) {
for (int i = 1; i <= 100; i++) {
countMe("t1", i);
}
}
} catch (Exception e){}
}
}; [/code]
… e, aparentemente, funcionou.
[]'s
Aqui você pode encontrar alguns vídeos sobre sincronized e threads
tem um que está em português e tal:
http://www.youtube.com/watch?v=upvyeBaW4kc
essa XTI é muito boa