[java] Java의 다중 스레드 환경에서 정적 메소드 동작

나를 괴롭 히고 내 마음 속에 몇 가지 논쟁을하는 간단한 어리석은 질문이 있습니다. 아래 질문에 대한 모든 의심을 버리고 싶습니다.

class Clstest{

    public static String testStaticMethod(String inFileStr) {

        // section 0

        // section 1

        // do something with inFileStr

        // section 2

        // section 3

        return inFileStr;

    }

}

5 개의 스레드가 각각 Clstest.testStaticMethod("arg-n")동시에 호출을 실행한다고 가정 해 보겠습니다 .

스레드 1은 Clstest.testStaticMethod("arg-1").

스레드 1이 섹션 1에 있으면 스레드 2가를 호출합니다 Clstest.testStaticMethod("arg-2").

그러면 스레드 1은 어떻게됩니까? 수면 상태가 될까요?

스레드 1이 일시 중지 된 섹션 1에서 실행을 재개 할 기회를 얻었을 때?

일이있을 때 어떻게됩니까 Clstest.testStaticMethod과 동일 Clstest.testStaticMethod다섯 개 스레드간에 공유?

inFileStr여러 스레드 에서 보낸 것을 교환 할 가능성이 있습니까?



답변

Hans Passant의 대답은 좋습니다. 그러나 나는 이것을 접하고 Java를 처음 접하는 사람을 위해 조금 더 간단한 수준에서 설명하려고 노력할 것이라고 생각했습니다. 여기 ..

자바의 메모리는 힙과 스택의 두 종류로 나뉩니다. 힙은 모든 객체가있는 곳이고 스택은 스레드가 작업을 수행하는 곳입니다. 각 스레드에는 자체 스택이 있으며 서로 스택에 액세스 할 수 없습니다. 각 스레드에는 현재 실행중인 코드 비트를 가리키는 코드에 대한 포인터도 있습니다.

스레드가 새 메서드를 실행하기 시작하면 해당 메서드의 인수와 지역 변수를 자체 스택에 저장합니다. 이러한 값 중 일부는 힙의 개체에 대한 포인터 일 수 있습니다. 두 스레드가 동시에 동일한 메서드를 실행하는 경우 둘 다 해당 메서드를 가리키는 코드 포인터가 있고 스택에 자체 인수 및 지역 변수 복사본이 있습니다. 스택의 사물이 힙의 동일한 객체를 가리키는 경우에만 서로 간섭합니다. 이 경우 모든 종류의 일이 발생할 수 있습니다. 그러나 Hans가 지적했듯이 문자열은 변경 불가능하므로 (변경할 수 없음) 이것이 “공유”되는 유일한 객체 인 경우 안전합니다.

너무 많은 스레드가 동일한 방법을 실행할 수 있습니다. 동시에 실행되지 않을 수도 있습니다. JVM이 하드웨어 스레드에 예약 된 OS 스레드에 Java 스레드를 매핑 할 때 시스템에있는 코어 수에 따라 다릅니다. 따라서 복잡한 동기화 메커니즘 을 사용하지 않고 이러한 스레드가 인터리브되는 방식을 거의 제어 할 수 없습니다 .

수면은 스레드가 자체적으로 수행하는 작업입니다.


답변

수면 상태가 될까요?

아니요, 스레드 실행은 의도적으로 서로 동기화하지 않는 한 다른 스레드에 영향을주지 않습니다. 두 개 이상의 프로세서 코어가있는 경우 모든 최신 시스템에서 해당 스레드가 정확히 동시에 실행될 가능성이 높습니다. 머신에 코어가 충분하지 않을 수 있으므로 5 개의 스레드를 시작할 때 그 가능성이 약간 줄어 듭니다. 운영 체제는 둘 중 하나를 선택해야하므로 실행할 시간이 주어집니다. 스레드 스케줄러의 작업입니다. 그러면 스레드는 “휴면”상태가 아니며 단순히 일시 중지되고 스레드 스케줄러가 실행할 기회를주기를 기다립니다. 스케줄러에 의해 중단 된 위치에서 다시 시작됩니다.

여러 스레드에서 보낸 inFileStr을 교환 할 가능성이 있습니까?

그러한 가능성은 없으며 스레드에는 자체 스택이 있으므로 모든 메서드 인수와 지역 변수는 각 스레드에 대해 고유합니다. 또한 문자열을 사용하면 문자열 이 변경 불가능하므로 이러한 스레드가 서로 간섭 할 수 없습니다.

인수가 다른 종류의 변경 가능한 객체에 대한 참조이면 그러한 보장이 없습니다. 또는 메서드 자체가 정적 변수 나 힙의 개체에 대한 참조를 사용하는 경우. 스레드가 오브젝트를 수정하고 다른 스레드가이를 읽을 때 동기화가 필요합니다. C # 언어 의 lock 키워드는 이러한 필수 동기화를 구현하는 표준 방법입니다. 메서드가 정적 이라는 사실 은 이러한 동기화가 절대 필요하지 않음을 의미하지 않습니다. 그냥 덜 동일한 개체를 (공유 액세스하는 스레드에 대해 걱정할 필요가 없기 때문에 ).


답변