제목은 다음과 같습니다.
공개 클래스 TestSync2는 실행 가능 {int b = 100; 동기화 된 void m1 () 던지기 인터럽트 exception {b = 1000; Thread.sleep (500); // 6 system.out.println ( "b =" + b); } 동기화 된 void m2 ()를 던지기 중간 exception {thread.sleep (250); // 5 b = 2000; } public static void main (String [] args)은 InterruptedException {testsync2 tt = new testsync2 (); 스레드 t = 새 스레드 (tt); // 1 T.start (); // 2 tt.m2 (); // 3 System.out.println ( "메인 스레드 B =" + TT.B); // 4} @override public void run () {try {m1 (); } catch (InterruptedException e) {e.printstacktrace (); }}}이 프로그램의 출력 결과?
프로그램 출력 결과
메인 스레드 B = 2000b = 1000
또는
메인 스레드 B = 1000b = 1000
지식 포인트를 확인하십시오
Java에서는 멀티 스레드 프로그램이 이해하고 디버그하기가 가장 어렵습니다. 우리가 상상했듯이 실행 결과는 여러 번 실행되지 않습니다. 따라서 자바에서 멀티 스레드는 매우 어렵습니다. 대학에서 C Language 2를 복용 할 때 모호하게 기억합니다. ++의 질문은 무엇이며 다른 많은 우선 순위 수준은 최종 출력 결과와 일치합니다. 이 유형의 질문에 대해 러너 우선 순위와 조합 질문을하고 싶습니다. 뒤로 물러서서 암송하지만 Java 멀티 스레딩은 여전히 잘 이해되어야합니다. 등받이는 할 수 없습니다.
간단한 분석을 시작하겠습니다.
이 질문에는 2 개의 스레드 (메인 스레드 메인, 하위 스레드)가 포함되며 키워드에는 동기화 및 스레드가 포함됩니다.
동기화 된 키워드는 여전히 상당히 복잡합니다 (때로는 잘 이해하지 못하므로 위의 질문에는 몇 가지 오해가 있습니다). 그 기능은 스레드 동기화를 실현하는 것입니다 (스레드 동기화를 구현하는 많은 방법이 있습니다. 후속 기사에서 이야기 할 다른 것들 일뿐입니다. 마스터 Doug Lea의 일부 구현은 신중하게 연구해야합니다). 그 임무는 동기화가 필요한 코드를 잠그므로 한 번만 한 번만 동기화 블록을 입력 할 수 있도록 (실제로는 비관적 전략 임) 스레드가 보안 만 기억하도록하는 것입니다.
일반 키워드 사용은 동기화되었습니다
위의 코드에서 동기화 된 사용은 실제로 두 번째 사례에 속합니다. 인스턴스 방법에 직접 작용 : 현재 인스턴스를 잠그는 것과 같습니다. 동기화 코드를 입력하기 전에 현재 인스턴스의 잠금을 얻어야합니다.
가능한 오해
1. 동기화 된 것을 이해하지 못하기 때문에 여러 번 멀티 스레딩을 통해 동기화 된 방법을 작동합니다. 두 스레드가 2 개의 다른 동기화 된 방법을 호출하면 관련이없는 것으로 생각됩니다. 이 아이디어는 오해입니다. 인스턴스 방법에 직접 작용 : 현재 인스턴스를 잠그는 것과 같습니다. 동기화 코드를 입력하기 전에 현재 인스턴스의 잠금을 얻어야합니다.
2. 동기화 된 메소드가 호출되는 경우. 일반적인 방법에 대한 또 다른 호출은 할 일이 없으며 두 사람은 대기 관계가 없습니다.
이들은 후속 분석에 매우 유용합니다.
Thread.sleep
현재 스레드 (즉, 메소드를 호출하는 스레드)를 일정 시간 동안 안전하게하여 다른 스레드에 계속 실행할 수있는 기회를 제공하지만 객체 잠금을 해제하지는 않습니다. 즉, 동기화 된 동기화가 빠르면 다른 스레드는 여전히 공유 데이터에 액세스 할 수 없습니다. 이 방법은 예외를 포착해야하며, 이는 후속 분석에 매우 유용합니다.
분석 프로세스
Java는 주요 방법에서 실행됩니다. 2 개의 스레드가 있다고 말하지만 여기에서 스레드 우선 순위를 수정하더라도 쓸모가 없습니다. 우선 순위는 두 프로그램이 아직 실행되지 않은 경우에만입니다. 이제이 코드가 실행되면 기본 스레드가 실행되었습니다. 속성 변수 int b = 100의 경우, 1 단계 (스레드 t = 새 스레드 (tt); // 1)를 수행 할 때 동기화 된 선언이 사용되기 때문에 가시성 문제가 없을 것입니다 (그리고 휘발성 선언이 사용되었다고 말할 필요가 없습니다). 스레드는 새 상태에 있으며 아직 작동하지 않았습니다. 2 단계가 실행되면 (t.start (); // 2) 시작 메소드가 호출되면 스레드가 실제로 시작되어 런닝 가능한 상태로 들어갑니다. 실행 가능한 상태는 실행 가능하고 모든 것이 준비되었음을 의미하지만 CPU에서 실행되어야한다는 의미는 아닙니다. 실제 실행이 있는지 여부는 서비스 CPU의 스케줄링에 따라 다릅니다. 여기서 3 단계를 수행 할 때는 먼저 잠금 장치를 얻어야합니다 (시작은 기본 메소드를 호출해야하며 사용이 완료된 후 모든 것이 준비되기 때문에 CPU에서 실행되어야한다는 의미는 아닙니다. 실제 실행이 서비스 CPU의 스케줄링에 따라 달라지고 실행 메소드가 호출되면 M1 메소드가 실행됩니다). 실제로 두 개의 동기화 된 방법에서 Shread.sheep가 문제가되는지 여부는 문제가되지 않으며 혼동에 어려움이 추가 될 수 있습니다. 3 단계가 실행되면 자식 스레드는 실제로 곧 준비되었지만 동기화 된 것이 존재하고 동일한 객체 역할을하기 때문에 하위 스레드가 기다려야합니다. 기본 방법의 실행 순서가 순차적으로 실행되므로 4 단계에 도달하기 전에 3 단계가 실행 된 후에 완료해야합니다. 3 단계 실행이 완료되므로 하위 스레드는 M1을 실행할 수 있습니다. 누가 멀티 스레드를 먼저 얻는 것이 문제가 있습니다. 4 단계가 먼저 얻어지면 메인 스레드 B = 2000. 자식 스레드 M1이 얻어지면 B가 1000에 할당되었거나 4 단계가 할당되기 전에 가능한 결과는 기본 스레드 B = 1000 또는 기본 스레드 B = 2000입니다. 6 단계가 여기에서 제거되면 B = 이전에 실행되고 메인 스레드 B = 이전에 불확실합니다. 그러나 6 단계가 존재하기 때문에 메인 스레드 B =가 앞쪽에 있으므로 1000 또는 2000과 같으면 상황에 따라 달라집니다. 그 후 B = 1000은 확실히 고정되어 있습니다.
멀티 스레딩에 대한 몇 가지 제안
후속 기사에서 공유 할 몇 가지 팁도 있습니다. 멀티 스레딩은 특히 중요하고 어렵습니다. 모두가 더 많은 시간을 보내길 바랍니다.
멀티 스레딩을위한 일부 디버깅 기술
중단 점으로 인해 모든 스레드는 중단 점을 통과 할 때 중지해야 하므로이 지점이 지속적으로 중단됩니다. 이는 매우 불편합니다. Eclispe에는 조건부 중단 점이 있으며 조건이 충족되면 중지 할 수 있으므로 편리합니다.
요약
위의 것은 편집자가 당신에게 소개 한 역사상 가장 어려운 Java 인터뷰 질문입니다. 나는 그것이 당신에게 도움이되기를 바랍니다. 궁금한 점이 있으면 메시지를 남겨 주시면 편집자가 제 시간에 답장을 드리겠습니다. Wulin.com 웹 사이트를 지원해 주셔서 대단히 감사합니다!