나는 자바에서 멀티 스레딩을 읽고 있었고 이것을 발견했습니다.
지역 변수는 Java에서 스레드로부터 안전합니다.
그 이후로 나는 어떻게 / 왜 지역 변수가 스레드로부터 안전하다고 생각하고 있습니다.
누군가 제발 알려주세요.
답변
스레드를 생성하면 자체 스택이 생성됩니다. 두 개의 스레드에는 두 개의 스택이 있으며 하나의 스레드는 다른 스레드와 스택을 공유하지 않습니다.
프로그램에 정의 된 모든 지역 변수는 스택에 메모리가 할당됩니다 (Jatin이 언급했듯이 여기서 메모리는 객체에 대한 참조 값 및 기본 유형에 대한 값을 의미합니다) (스레드에 의한 각 메서드 호출은 자체 스택에 스택 프레임을 생성합니다). 이 스레드에 의해 메서드 실행이 완료되면 스택 프레임이 제거됩니다.
이 개념을 이해하는 데 도움이 될 수 있는 YouTube의 스탠포드 교수의 훌륭한 강의가 있습니다.
답변
지역 변수는 각 스레드의 자체 스택에 저장됩니다. 즉, 로컬 변수는 스레드간에 공유되지 않습니다. 이는 또한 모든 로컬 기본 변수가 스레드로부터 안전함을 의미합니다.
public void someMethod(){
long threadSafeInt = 0;
threadSafeInt++;
}
객체에 대한 로컬 참조는 약간 다릅니다. 참조 자체는 공유되지 않습니다. 그러나 참조 된 객체는 각 스레드의 로컬 스택에 저장되지 않습니다. 모든 개체는 공유 힙에 저장됩니다. 로컬에서 생성 된 객체가 생성 된 메서드를 이스케이프하지 않는 경우 스레드로부터 안전합니다. 실제로 이러한 메서드 나 개체 중 어느 것도 다른 스레드에서 전달 된 개체를 사용할 수없는 한 다른 메서드 및 개체에 전달할 수도 있습니다.
답변
기능 정의와 같은 방법을 생각하십시오. 두 스레드가 동일한 메서드를 실행하면 전혀 관련이 없습니다. 그들은 각각 각 지역 변수의 고유 한 버전을 만들고 어떤 식 으로든 서로 상호 작용할 수 없습니다.
변수가 로컬이 아닌 경우 (예 : 클래스 수준에서 메서드 외부에 정의 된 인스턴스 변수), 메서드의 단일 실행이 아닌 인스턴스에 연결됩니다. 이 경우 동일한 메서드를 실행하는 두 개의 스레드는 둘 다 하나의 변수를 볼 수 있으며 스레드로부터 안전하지 않습니다.
다음 두 가지 경우를 고려하십시오.
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;
}
}
첫 번째에서 동일한 인스턴스에서 실행되는 두 개의 스레드 NotThreadsafe
는 동일한 x를 보게됩니다. 스레드가 x를 변경하려고하기 때문에 위험 할 수 있습니다! 두 번째로 동일한 인스턴스에서 실행되는 두 개의 스레드 Threadsafe
는 완전히 다른 변수를 보게되며 서로 영향을 미칠 수 없습니다.
답변
각 메서드 호출에는 고유 한 지역 변수가 있으며 분명히 메서드 호출은 단일 스레드에서 발생합니다. 단일 스레드에 의해서만 업데이트되는 변수는 본질적으로 스레드로부터 안전합니다.
그러나 이것이 정확히 무엇을 의미하는지 주시 하십시오. 변수 자체에 대한 쓰기 만 스레드로부터 안전합니다. 참조하는 객체에서 메서드를 호출하는 것은 본질적으로 스레드로부터 안전하지 않습니다 . 객체의 변수를 직접 업데이트하는 경우에도 마찬가지입니다.
답변
Nambari와 같은 다른 답변 외에도.
귀찮은 유형 메서드에서 지역 변수를 사용할 수 있음을 지적하고 싶습니다.
이 메소드는 스레드 안전성을 손상시킬 수있는 다른 스레드에서 호출 될 수 있으므로 Java는 성가신 유형에서 사용되는 모든 지역 변수를 최종적으로 선언하도록 강제합니다.
다음 불법 코드를 고려하십시오.
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();
}
}
자바가 이것을 허용했다면 (C #이 “클로저”를 통해하는 것처럼), 지역 변수는 모든 상황에서 더 이상 스레드 세이프가되지 않습니다. 이 경우 i
모든 스레드의 끝에 있는의 값은 100
.
답변
스레드에는 자체 스택이 있습니다. 두 개의 스레드에는 두 개의 스택이 있으며 하나의 스레드는 다른 스레드와 스택을 공유하지 않습니다. 지역 변수는 각 스레드의 자체 스택에 저장됩니다. 즉, 로컬 변수는 스레드간에 공유되지 않습니다.
답변
기본적으로 Java에는 클래스 정보 및 데이터를 저장하는 네 가지 유형의 저장소가 있습니다.
메서드 영역, 힙, JAVA 스택, PC
그래서 메소드 영역과 힙은 모든 스레드에서 공유되지만 모든 스레드는 자체 JAVA 스택과 PC를 가지고 있으며 다른 스레드에서는 공유하지 않습니다.
Java의 각 메소드는 스택 프레임입니다. 따라서 스레드가 하나의 메소드를 호출하면 스택 프레임이 JAVA 스택에로드되고 해당 스택 프레임 및 관련 피연산자 스택에있는 모든 로컬 변수는 다른 사용자가 공유하지 않습니다. PC는 메소드의 바이트 코드에서 실행할 다음 명령어 정보를 갖게됩니다. 따라서 모든 지역 변수는 THREAD SAFE입니다.
@Weston도 좋은 답변을 제공했습니다.