Sincronização de Thread's

Ola, meus amigos!
Tenho uma dúvida que está me dando muito trabalho, já fiz várias pesquisas na internet, vídeo aulas e afins, mas a dúvida persisti ou ao menos parte dela.

Então vou lhes perguntar.
Como eu posso sincronizar um Objeto entre várias Thread?s???

Ok, para contextualizar, eu sei como criar uma Thread (estendendo Thread ou implementando Runnable), sei como sincronizar um Objeto (dados) pertencente a uma thread, pode ser sincronizado:

a) Criando várias threads a partir do MESMO objeto da classe que implementa Runnable e declarando os métodos que alteram os dados como synchronized
b) Criando várias threads a partir de VÁRIOS objetos da classe que implementa Runnable e declarara os métodos que alteram os dados como synchronized e os dados como static

Mas o que eu quero é alterar os dados que estão em uma classe diferente da classe que implementa Runnable, por exemplo e também não são static

Suponha que eu tenho um Objeto servidor de uma classe SERVIDOR
E vários objetos escravos de uma classe ESCRAVO

Então o servidor inicia sua atividade abrindo um socket para escutar os escravos…
Daí quando um escravo se conecta o servidor cria uma Thread que vai gerir a conexão com o escravo, então o escravo envia uma mensagem contendo uma lista de arquivos e então essa mensagem é capturada e processada pela Thread que o servidor criou para gerir a conexão…

Como eu poderia então fazer com que essa Thread colocasse os dados em uma lista de arquivos do servidor (um atributo do objeto servidor), mas de forma que somente um método desses pudesse está ativo por vez, ou seja, embora existam varias threads e elas trabalhem separadamente na hora de ?gravar? uma informação no servidor elas deveriam sincronizar…
Eu conseguir esse efeito mas acho que ainda não está da melhor forma, o que eu fiz foi fazer cada Thread atualizar sua própria lista de arquivos e então chamar um método do servidor que é sincronizado para atualizar a lista do servidor, MAS, achei essa solução meia boca, eu pensei em usar o wait e notify mas, fico a pensar se não há uma forma apenas usando synchronized…

Então de novo!

O que eu quero é que várias threads alterem dados de uma outra classe mas que essa alteração seja sincronizada, (uma após a outra), por exemplo se eu tenho o método adicionarParaServidor, então uma Thread só pode iniciar este serviço depois uma outra tiver terminado… eu não estou conseguindo fazer isso!

Para ficar ainda mais claro segue o exemplo de código abaixo:

Essa classe deveria ter o método processarLista ?Sincronizado?

[code]public class Escravo implements Runnable {
private static int base = 0;

@Override
public void run() {
    processarLista();
}

public synchronized void processarLista() {
    for(int i = 0; i < 5; i++) {
        try {
            System.out.println(Thread.currentThread().getName() + " aguardando processamento...");
			Thread.sleep(1000);
        }
        catch (InterruptedException ex) {
            System.err.println("Erro ao executar sleep.");
        }
    }
}

}[/code]

Está e a classe Main

[code]public class Main {
public static void main(String[] args) throws InterruptedException {
System.out.println(“Estudo de Threads. Executando…”);

    new Thread(new Escravo(), "Escravo 1").start();
    new Thread(new Escravo(), "Escravo 2").start();
    new Thread(new Escravo(), "Escravo 3").start();
    new Thread(new Escravo(), "Escravo 4").start();
}

}
[/code]
Isso resultada na saída…

Escravo 1 aguardando processamento...
Escravo 3 aguardando processamento...
Escravo 2 aguardando processamento...
Escravo 4 aguardando processamento...
Escravo 1 aguardando processamento...
Escravo 4 aguardando processamento...
Escravo 2 aguardando processamento...
Escravo 3 aguardando processamento...
Escravo 1 aguardando processamento...
Escravo 3 aguardando processamento...
Escravo 2 aguardando processamento...
Escravo 4 aguardando processamento...
Escravo 1 aguardando processamento...
Escravo 3 aguardando processamento...
Escravo 2 aguardando processamento...
Escravo 4 aguardando processamento...
Escravo 1 aguardando processamento...
Escravo 3 aguardando processamento...
Escravo 2 aguardando processamento...
Escravo 4 aguardando processamento...

O que eu não entendo é se o método processarLista lista é sincronizado por que não se repeti todo o for da primeira thread, depois o da segundo, terceira e assim por diante, por que elas continuam a correr paralelamente…

Contudo se eu fizer:

[code]public class Main {
public static void main(String[] args) throws InterruptedException {
System.out.println(“Estudo de Threads. Executando…”);

    Escravo escravo = new Escravo();
    
    new Thread(escravo, "Escravo 1").start();
    new Thread(escravo, "Escravo 2").start();
    new Thread(escravo, "Escravo 3").start();
    new Thread(escravo, "Escravo 4").start();
}

}[/code]

Aí então a saída é:

Escravo 1 aguardando processamento...
Escravo 1 aguardando processamento...
Escravo 1 aguardando processamento...
Escravo 1 aguardando processamento...
Escravo 1 aguardando processamento...
Escravo 4 aguardando processamento...
Escravo 4 aguardando processamento...
Escravo 4 aguardando processamento...
Escravo 4 aguardando processamento...
Escravo 4 aguardando processamento...
Escravo 2 aguardando processamento...
Escravo 2 aguardando processamento...
Escravo 2 aguardando processamento...
Escravo 2 aguardando processamento...
Escravo 2 aguardando processamento...
Escravo 3 aguardando processamento...
Escravo 3 aguardando processamento...
Escravo 3 aguardando processamento...
Escravo 3 aguardando processamento...
Escravo 3 aguardando processamento...

Exatamente o que eu queria, a execução não está em ordem: 1, 2, 3, 4 MAS cada for é executado todo e só depois é passado para outro Thread

Mas isso só ocorre por que eu estou criando as várias Threads a partir do mesmo objeto da classe que implementa RunnableO que eu quero saber é como conseguir o mesmo feito (?a forma correta?) mas a partir de objetos diferentes…

Eu acredito que minha compreensão sobre como as Threads funcionam será muito ajudada se eu puder entender isto.

Eu sei que vão dizer, mas tu quer que as Thread?s trabalhem sequencialmente… ???
SIM, isso é importante para o meu entendimento de como essa execução funciona e de como as Threads funcionam, depois vou estender para algo semelhante ao pool de tarefas…

Grato e desculpe o tamanho do tópico.

Abaixo foto do programa no qual estou usando isso, é um trabalho de sistemas distribuídos.

https://sites.google.com/site/autotechsoftware/home/servidorarquivos.png

Nota: Coloquei como URL porque senão vai ficar muito ruim de ler…

Jorge,

Eu em particular recomendo usar um objeto que permita alguma concorrência como um ConcurrentHashMap ou um ConcurrentSkipListMap ou Set.

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html

Dica: a pior forma de resolver esse problema é ficar pensando em “sincronização de threads”. Você só vai queimar a cabeça e inventar alguma solução muito complexa e difícil de debugar.

O correto é você definir o seu problema em termos de “tasks” ou “actors”.
Você vai ver que isso torna as coisas mais simples. Em particular, em 90% dos problemas que conheço basta você conhecer o conceito de “consumers” e “producers”.

entanglement, eu lhe entendo amigo, conheço o conceito de produtores e consumidores com wait e notify, eu não gostaria de usar algo muito “abstrato” em Java por que este estudo é também muito em relação a própria natureza das Threads do ponto de vista dos S.O, assim que entender “legal” o conceito e as coisas correlatas passarei de Java para C, C++, C# afim de melhorar uma minha experiência neste assunto, então minha pergunta é mais para que eu possa entender por que a sincronização não está acontecendo como eu “equivocadamente” supunha que aconteceria.

Eu pretendo claro, muito certamente avançar neste tópico em Java mas no momento é uma “primeiro” contato e estou dirimindo algumas dúvidas que acredito serem básicas, MAS que estão me dando algum trabalho!

Grato pelas respostas…

Vou dar um exemplo. Quando precisamos escrever coisas de alto desempenho em C/C++ costumamos usar uma biblioteca como a MPI ou o OpenMP. Você não se preocupa tanto com essa história de threads em OpenMP porque isso é levado em conta pela própria biblioteca.

Sincronização de threads é algo parecido com “goto” - só que muito pior, já que “goto” pode ser transformado facilmente em código estruturado, mas threads (só com start, wait/notify etc.) não levam naturalmente a estruturas simples e fáceis de reconhecer.

A sincronização não deve ser codificada diretamente no seu código; em vez disso, é necessário seguir um padrão qualquer (como o de actors, producers/consumers etc.).

Mas supondo que por razões didáticas eu queria “experimentar” para entender a razão pelas quais as coisas são de outra forma?
Eu sempre busco entender o caminho difícil para então ir pelo caminho mais fácil como forma de saber:
“É… realmente as coisas estão melhores assim…”

Cito exemplo da programação linear, eu estudei um pouco de assembly x86 para “experimentar” o que seria codificar uma programa como no inicio da programação usei o MASM e o RadASM e foi uma boa experiência embora não vá usar isso na “vida real” deu pra ver como as coisas eram e como elas são hoje… mas ver mesmo por dentro… não apenas uma citação de livro… programo a algum tempo em P.E hoje estou muito voltado a P.O.O mas consigo ver as “melhorias” da P.O.O em relação a P.E, contudo seu eu não tivesse visto de fato o que é P.E eu pessoalmente não me sentiria tão a vontade, sempre busco ao menos entender o detalhes é claro não dá pra saber tudo de tudo, mas eu tento ao menos saber o básico, em relação a Threads este é um tema muito extenso perfazendo programação (várias linguagens) e S.O (vários sistemas) e meu interesse é justamente no princípio, na base…
Sobre a qual eu irei construir algum conhecimento, mas para isso preciso “exaurir” minhas dúvidas básicas sobre Threads.

Não é uma questão de necessidade da resolução do problema é mais uma questão de necessidade de compreensão do tema.