Eu estava lendo multi-threading em Java e me deparei com isso
Variáveis locais são thread-safe em Java.
Desde então, tenho pensado em como / por que variáveis locais são thread-safe.
Alguém pode me avisar.
Eu estava lendo multi-threading em Java e me deparei com isso
Variáveis locais são thread-safe em Java.
Desde então, tenho pensado em como / por que variáveis locais são thread-safe.
Alguém pode me avisar.
Respostas:
Ao criar um thread, ele terá sua própria pilha criada. Dois threads terão duas pilhas e um thread nunca compartilha sua pilha com outro thread.
Todas as variáveis locais definidas em seu programa terão memória alocada na pilha (como Jatin comentou, memória aqui significa, valor de referência para objetos e valor para tipos primitivos) (Cada chamada de método por um thread cria um frame de pilha em sua própria pilha). Assim que a execução do método for concluída por esta thread, o stack frame será removido.
Há uma ótima palestra do professor de Stanford no youtube que pode ajudá-lo a entender esse conceito.
Variáveis locais são armazenadas na própria pilha de cada thread. Isso significa que variáveis locais nunca são compartilhadas entre threads. Isso também significa que todas as variáveis primitivas locais são thread-safe.
public void someMethod(){
long threadSafeInt = 0;
threadSafeInt++;
}
As referências locais a objetos são um pouco diferentes. A referência em si não é compartilhada. O objeto referenciado, entretanto, não é armazenado na pilha local de cada thread. Todos os objetos são armazenados no heap compartilhado. Se um objeto criado localmente nunca escapar do método em que foi criado, ele é seguro para threads. Na verdade, você também pode passá-lo para outros métodos e objetos, desde que nenhum desses métodos ou objetos torne o objeto passado disponível para outras threads
Pense em métodos como definições de funcionalidade. Quando dois threads executam o mesmo método, eles não estão de maneira alguma relacionados. Cada um deles criará sua própria versão de cada variável local e não poderão interagir uns com os outros de nenhuma forma.
Se as variáveis não são locais (como variáveis de instância definidas fora de um método no nível de classe), então elas são anexadas à instância (não a uma única execução do método). Nesse caso, dois threads executando o mesmo método veem a mesma variável, e isso não é seguro para threads.
Considere estes dois casos:
public class NotThreadsafe {
int x = 0;
public int incrementX() {
x++;
return x;
}
}
public class Threadsafe {
public int getTwoTimesTwo() {
int x = 1;
x++;
return x*x;
}
}
No primeiro, dois threads em execução na mesma instância de NotThreadsafe
verão o mesmo x. Isso pode ser perigoso, porque os tópicos estão tentando mudar x! No segundo, dois threads em execução na mesma instância de Threadsafe
verão variáveis totalmente diferentes e não podem afetar um ao outro.
Cada invocação de método possui suas próprias variáveis locais e, obviamente, uma invocação de método ocorre em um único thread. Uma variável que é atualizada apenas por um único thread é inerentemente segura para thread.
No entanto , fique atento ao que exatamente significa isso: apenas as gravações na variável em si são seguras para threads; chamar métodos no objeto a que se refere não é inerentemente thread-safe . O mesmo vale para a atualização direta das variáveis do objeto.
Além das outras respostas, como a de Nambari.
Gostaria de salientar que você pode usar uma variável local em um método do tipo anônimo:
Este método pode ser chamado em outras threads que podem comprometer a threadsafety, então java força todas as variáveis locais usadas em tipos anônimos a serem declaradas como finais.
Considere este código ilegal:
public void nonCompilableMethod() {
int i=0;
for(int t=0; t<100; t++)
{
new Thread(new Runnable() {
public void run() {
i++; //compile error, i must be final:
//Cannot refer to a non-final variable i inside an
//inner class defined in a different method
}
}).start();
}
}
Se o java permitisse isso (como o C # faz por meio de "fechamentos"), uma variável local não seria mais threadsafe em todas as circunstâncias. Nesse caso, o valor de i
no final de todos os threads não tem garantia de ser 100
.
O thread terá sua própria pilha. Dois threads terão duas pilhas e um thread nunca compartilha sua pilha com outro thread. Variáveis locais são armazenadas na própria pilha de cada thread. Isso significa que variáveis locais nunca são compartilhadas entre threads.
Basicamente, quatro tipos de armazenamento existem em java para armazenar informações e dados da classe:
Área de Método, Pilha, Pilha JAVA, PC
portanto, a área do método e o heap são compartilhados por todos os threads, mas cada thread tem sua própria pilha JAVA e PC e isso não é compartilhado por nenhum outro thread.
Cada método em java é como Stack frame. portanto, quando um método é chamado por um thread, esse quadro de pilha é carregado em sua pilha JAVA. Todas as variáveis locais que estão nesse quadro de pilha e a pilha de operandos relacionados não são compartilhados por outros. O PC terá informações da próxima instrução a ser executada no código de bytes do método. então todas as variáveis locais são THREAD SAFE.
@Weston também deu uma boa resposta.
Apenas variáveis locais são armazenadas na pilha de threads.
A variável local que é primitive type
(por exemplo, int, long ...) é armazenada no thread stack
e como resultado - outro segmento não tem acesso a ele.
A variável local que é reference type
(sucessora de Object
) contém 2 partes - endereço (que é armazenado em thread stack
) e o objeto (que é armazenado em heap
)
class MyRunnable implements Runnable() {
public void run() {
method1();
}
void method1() {
int intPrimitive = 1;
method2();
}
void method2() {
MyObject1 myObject1 = new MyObject1();
}
}
class MyObject1 {
MyObject2 myObject2 = new MyObject2();
}
class MyObject2 {
MyObject3 myObject3 = MyObject3.shared;
}
class MyObject3 {
static MyObject3 shared = new MyObject3();
boolean b = false;
}