[SCJP] dúvida nos métodos notifyAll e wait()

OLá!
Estou com uma dúvida com relação a eses métodos no seguinte caso:

Suponha que existam 10 Threads bloqueadas usando o método wait() aguardando liberação, quando o método notifyAll() é executado a JVM irá desbloquear o método com maior prioridade, certo?
A dúvida é: O que ocorrerá com os outros Threads que também aguardam o desbloqueio? Elas também serão executadas? Em que ordem?

Forte Abraço.
Paulo Gervásio.

Serão desbloqueadas sim, porém você não consegue saber a ordem… Tudo depende de como o escalonador vai fazer para dar prioridades aos processos.

O problema com Threads é o mesmo que acontece com os Semáforos e Processos das aulas de SO!

[quote=gervas-IO]OLá!
Estou com uma dúvida com relação a eses métodos no seguinte caso:

Suponha que existam 10 Threads bloqueadas usando o método wait() aguardando liberação, quando o método notifyAll() é executado a JVM irá desbloquear o método com maior prioridade, certo?
A dúvida é: O que ocorrerá com os outros Threads que também aguardam o desbloqueio? Elas também serão executadas? Em que ordem?

Forte Abraço.
Paulo Gervásio.[/quote]

Se você olhar a documentação você vai ver que a realidade é mais obscura que parece.

Vou fazer a tradução literal, para economizar seu tempo.

[quote=Javadoc]
Acorda todas as threads que estão esperando no monitor deste objeto. Uma thread espera no monitor de um objeto ao chamar um dos métodos wait.
As threads acordadas não poderão prosseguir até a thread corrente liberar o “lock” (trava) neste objeto. As threads acordadas irão competir da maneira usual com outras threads que possam estar ativamente competindo para sincronizar com este objeto; por exemplo, as thread acordadas não têm nenhum privilégio ou desvantagem previsível para ser a próxima thread que irá travar este objeto.
Este método deve ser apenas chamada por uma thread que é a proprietária do monitor deste objeto. Veja o método “notify” para uma descrição dos modos em que uma thread pode se tornar a proprietária de um monitor.[/quote]
Ele se referiu ao javadoc do método notify.

Ou seja,

Donde se conclui que:
a) Você está confundindo “notify” com "notifyAll"
b) Não é porque a thread tem prioridade maior que ela vai ser acordada primeiro. Na verdade, o sistema operacional pode optar por acordar uma thread de prioridade MENOR primeiro, se o sistema operacional decidir que é hora de usar um algoritmo usado em vários sistemas operacionais, que é a “inversão de prioridade”. Como o Java roda em vários sistemas operacionais, o pessoal da Sun optou por dizer que a ordem em que as threads serão acordadas é indefinida - ou seja, está fora da responsabilidade do Java.

Só para exemplificar melhor esse conceito. Se você sempre acordar a thread de maior prioridade, você corre o risco de uma das threads nunca executar.
Suponha que exista uma thread de prioridade baixa, e outras de prioridade alta sempre entram na fila. Aquela thread poderia nunca ser executada, se o numero de threads de prioridade alta fosse grande o suficiente (uma condição conhecida como starvation).

O que os SOs tipicamente fazem, então? Cada vez que uma thread perde o direito de executar, ela aumenta um pouco sua prioridade. Esse aumento “virtual” é zerado assim que a thread executa. Isso garante que mesmo uma thread de prioridade baixíssima rode. Como não há como prever em que pé está o controle do SO, assim que uma thread acorda com o notifyAll(), também não podemos prever o que entrará no bloco sincronizado e o que voltará a dormir.

Fiquei confuso agora.

Só pra fechar:
notifyAll(); // chama algum Thread baseado em prioridades definidas pelo SO
notify(); //chama o primeiro Thread que recebeu o bloqueio

Essa afirmação sobre notify está correta?

Grato.
Paulo Gervásio.

Leia a documentação que o thingol passou. Ela é enfática em dizer que a “escolha é arbitrária e ocorre pela escolha da implementação”. Onde você leu aí que a implementação se baseia numa fila?

O notify() acorda uma única thread, que esteja esperando no bloco. Que thread, é o SO que decide.

O problema de acordar uma thread só é que essa thread pode não querer processar naquele momento, e voltar a dormir. E aí, nenhuma outra thread irá concorrer pelo bloco. Nesse caso, seu sistema trava, sem a presença de um deadlock.

Por isso é preferível usar o notifyAll(). É um pouco mais lento, mas mais garantido.

Como isso poderia acontecer?

Como isso poderia acontecer?[/quote]

Pode acontecer, por exemplo, se a thread em questão fizer uma operação de I/O, sobre um arquivo bloqueado. O deadlock ocorrerá se esse arquivo nunca for liberado. Mas, enquanto isso não ocorrer, a thread será colocada em espera, e nenhuma outra será acordada para processar naquela momento, o que deixa todo seu sistema ocioso.