Se o acesso aos dados mutáveis compartilhados não puder ser sincronizado, as consequências podem ser terríveis, mesmo que a variável seja atomicamente legível e gravável.
Vamos considerar um problema de sincronização de threads. Para sincronização de threads, a biblioteca de classes Java fornece o método Thread.stop, mas não vale a pena promovê-lo porque é inerentemente inseguro. Seria melhor usar polling, como o programa a seguir.
Copie o código do código da seguinte forma:
importar java.util.concurrent.TimeUnit;
classe pública StopThread {
/**
* @param argumentos
*/
stopRequested booleano estático privado;
público estático void principal(String[] args)
lança InterruptedException{
Thread backgroundThread = new Thread(new Runnable() {
@Substituir
execução void pública() {
int eu = 0;
while(!stopRequested){
eu++;
System.out.println(i);
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = verdadeiro;
}
}
Você pode pensar que após a execução deste programa por cerca de um segundo, o thread principal define stopRequested como verdadeiro, fazendo com que o novo thread em segundo plano pare. Na verdade, esse não é o caso, porque o thread em segundo plano não pode ver a alteração neste. valor, então ele continuará em loop indefinidamente, esta é a consequência de não sincronizar os dados. Então, vamos fazer isso de forma síncrona.
Copie o código do código da seguinte forma:
importar java.util.concurrent.TimeUnit;
classe pública StopThread {
/**
* @param argumentos
*/
stopRequested booleano estático privado;
privado estático sincronizado void requestStop(){
stopRequested = verdadeiro;
}
privado estático sincronizado booleano stopRequested(){
retornar parada solicitada;
}
público estático void principal(String[] args)
lança InterruptedException{
Thread backgroundThread = new Thread(new Runnable() {
@Substituir
execução void pública() {
int eu = 0;
while(!stopRequested()){
eu++;
System.out.println(i);
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
Isso atinge a sincronização de dados. É importante notar que tanto o método de gravação (requestStop) quanto o método de leitura (stopRequested) precisam ser sincronizados, caso contrário, ainda não estão sincronizados no verdadeiro sentido.
Além disso, podemos usar o modificador de variável volátil para concluir tarefas de sincronização de forma mais simples.
Copie o código do código da seguinte forma:
importar java.util.concurrent.TimeUnit;
classe pública StopThread {
/**
* @param argumentos
*/
privado estático volátil booleano stopRequested;
público estático void principal(String[] args)
lança InterruptedException{
Thread backgroundThread = new Thread(new Runnable() {
@Substituir
execução void pública() {
int eu = 0;
while(!stopRequested){
eu++;
System.out.println(i);
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = verdadeiro;
}
}