2012-03-30 3 views
1

스레드 관점에서 블록, 대기 및 잠금이란 무엇입니까? 오히려 모든 작업에서이 세 가지를 모두 가지고 있어야합니까? 예를 들어, 생산자 - 소비자 패턴에서 이러한 것들을 구현하는 방법. 미리 감사드립니다.스레드 동작

답변

2

차단 작업은 작업이 완료 될 때까지 스레드를 차단하는 작업입니다. 블로킹 스레드 란 스레드가 깨어날 때까지 스레드를 실행하지 않도록 스레드 스케줄러 (일반적으로 운영 체제, 사용자 수준의 스레드 라이브러리가 있음)에게 알리는 프로세스입니다. 차단 작업에는 여러 가지가 있으며 파일 I/O가 그 예입니다. 다른 모든 블로킹 작업과 마찬가지로 해당 작업 (이 경우 파일 I/O)이 완료 될 때까지 메서드가 반환되지 않습니다.

wait은 스레드 동기화에 사용되는 특정 종류의 차단 작업입니다. 특히, 다른 스레드가 깨울 때까지 wait이라는 스레드를 차단하십시오. " 자바에서는 대기 시간이 method입니다. 해당 웨이크 업 방법은 notify입니다.

잠금은 "이 코드 영역으로 제한된 수의 스레드 만 허용합니다"라는 더 높은 수준의 추상화입니다. 가장 일반적으로 제한된 수는 1입니다.이 경우, 뮤텍스 (자세한 내용은 this SO answer에 설명되어 있습니다)는 C와 같은 하위 언어에서 선호되는 잠금 프리미티브입니다. Java에서 가장 일반적인 잠금 프리미티브는 모니터. 객체의 모니터 (모든 객체에는 모니터가 있음)를 소유하고 모니터에서 기다리고 모니터에서 대기중인 스레드를 깨우는 개념이 있습니다. 우리는 이것을 어떻게 성취합니까? 모니터를 기다리는 데 wait 메서드를 사용하고 모니터에서 대기중인 스레드 중 하나를 깨우려면 notify 메서드를 사용합니다.

지금은 동시성으로 시작한 것만 큼 그리스어와 비슷할 것입니다. 생산자 - 소비자 패턴을 구현하려면 가장 일반적인 전략은 두 개의 세마포어 (뮤텍스를 사용하여 버퍼). 세마포어는 일반적으로 뮤텍스로 구현되지만 일부 리소스를 계산할 수 있으므로 고차원 구조입니다. 따라서 버퍼의 항목 수를 세마포어 하나를 유지하고 버퍼의 빈 공간 수를 계산하려면 세마포를 유지합니다. 생성자는 빈 공간 세마포어를 기다리고 공간이 사용 가능할 때마다 항목을 버퍼에 추가하고 소비자는 항목 세마포어를 기다리고 항목이 사용 가능할 때마다 항목을 소비합니다.

이제는 이러한 내용을 정의했지만 실제로는 을 사용하는 방법에 대해 이야기하지 않았습니다. 그러나 대학 과정에서 여러 강의를 치를만한 가치가 있으며, StackOverflow 답변에 대해서는 너무 많은 것입니다. 스레딩을 시작하는 방법으로 the Java tutorials의 동시성 수업을 권하고 싶습니다. 또한 웹에서 대학 과정을 둘러보십시오. 많은 학교에서는 온라인으로 메모를 게시하므로 조금만 검색하면 고품질 자료를 찾을 수 있습니다. 프로세스가 무엇인지 당신이이 글을 읽고 시작하기 전에 스레드가 무엇인지 잘 알고 있는지 확인

대기 및 차단 I/O 사이의 차이에 대한 설명과 :


편집 . 나는 처음 네 단락 인 this SO answer에서 설명을하고,보다 상세한 설명은 Wikipedia이다 (역사적 맥락은 적긴하지만).

각 스레드에는 매우 중요한 정보가 있습니다. 명령 포인터 (각 스레드와 관련된 중요한 정보가 있지만 중요한 것은 아닙니다). 명령 포인터는 현재 실행중인 바이트 코드 명령에 대한 JVM 관리 포인터입니다. 명령을 실행할 때마다 (각 명령은 "x 개체에 대한 호출 메서드 foo과 같은 매우 간단한 작업의 추상 표현입니다.) 명령 포인터는"다음 명령 "으로 이동합니다. 프로그램을 실행하려면 JVM main의 시작 명령 포인터를 설정하고, 명령어를 실행하는 프로그램이 어떻게 든 종료까지 전진 명령 포인터 이동 유지한다.

일부 이벤트까지 전진 이동 명령 포인터 정지차단 동작은 명령 포인터 발생할 발생 다시 앞으로 움직여야합니다. 확실히 블로킹 작업을 시작한 스레드는이 스레드의 명령 포인터가 앞으로 이동하지 않기 때문에이 이벤트를 발생시킬 수 없습니다. 즉 스레드가 doin입니다. 아무것도 아냐.

이제 차단 작업에는 여러 가지 종류가 있습니다. 하나는 I/O를 차단하고 있습니다. 예를 들어, System.out.println을 호출하면 텍스트가 콘솔에 기록 될 때까지 println 메서드가 반환되지 않습니다. 이 경우, 명령 포인터는 System.out.println 어딘가에서 멈추고 운영 체제은 콘솔 인쇄가 끝날 때마다 스레드가 깨어나도록 신호를 보냅니다. 따라서 스레드는 자신의 명령 포인터를 다시 움직여야 할 필요는 없지만, 텍스트가 콘솔에 기록 된 직후에는이 메소드가 여전히 리턴됩니다. 그래서, 매우 높은 수준의 :

  • 스레드 0 전화 System.out.println("foo")
  • 스레드 0의 명령 포인터 운영 체제가 완료되면 운영 체제가 쓰기 콘솔
  • 에 "foo는"기록하면서 이동 중지 콘솔에서는 JVM에 알리고 JVM은 자동으로 스레드 0의 명령 포인터 이동을 다시 시작합니다. 이 모든 일은 프로그래머가 System.out.println에 대해 생각할 필요가 없다면 발생합니다.

블로킹 동작의 다른 완전히 분리 종류의 Object.wait 방법으로 캡슐화된다.스레드가 Object.wait을 호출 할 때마다 해당 스레드의 명령 포인터는 움직이지 않지만 운영 체제가 명령 포인터의 이동을 다시 시작하는 대신 다른 스레드이 작업을 수행합니다. 이 경우 스레드의 명령 포인터가 다시 시작되도록하는 외부 이벤트는 없지만 (블록 I/O의 경우처럼) 은 프로그램 내부 이벤트 인입니다. 앞에서 말한 것처럼 다른 스레드는 Object.notify을 호출하여 명령 포인터를 다시 시작합니다. 그래서, 매우 높은 수준의 :

  • 스레드
  • 스레드 0의 명령 포인터가 1 전화 x.notify() 동일한 개체에
  • 스레드를 움직이지 일부 개체에서 0 전화 x.wait()x
  • 스레드 0의 명령 포인터 시작 다시 이동
  • 스레드 0과 스레드 1이 현재 동시에 실행 중임

JVM과 운영 체제가 지금 당신을 위해 모든 일을 처리하지는 않는다. 여전히 실제로 대부분의 작업을 수행하지만 실제로는 waitnotify을 호출하고 스레드간에 통신하고 잠금을 구현하는 방법을 고려해야합니다.

그래서이 이야기에는 두 가지 도덕이 있습니다. 첫 번째는 I/O 및 wait을 차단하는 것이 완전히 다른 짐승입니다. 두 경우 모두 스레드가 차단되지만, I/O를 차단하는 경우 스레드는 운영 체제에서 자동으로 깨우지 만 wait 경우 스레드는 깨우기 위해 notify을 호출하는 다른 스레드에 의존해야합니다. 두 번째는 동시 프로그래밍이 직렬 프로그래밍보다 추론하기가 더 어렵다는 것입니다. 이 답변에 넣은 장난감 예제는 실제로 두 번째 요점을 정의하지 않습니다.

+0

당신에 따르면, wait(), notify()가 사용된다. 그래서이 연산들이 입력을 막는가? 그래서 우리는 wait()를 사용할 때, 암묵적으로 IO의 차단이 일어난다 고 말할 수 있습니다 ... – UVM

+0

@UNNI 아니오, 그렇습니다. 블로킹 연산은 스레드가 일정 시간 동안 스레드를 실행하지 못하도록하고, 입력은 블로킹 연산의 * 종류 *이며, wait는 * 블로킹 연산의 다른 종류 *입니다. 이를 반영하여 답변을 업데이트했습니다. –

+0

, 대답에서 대기 작업은 스레드 동기화에 사용되며 IO를 차단합니다. 기본적으로 프로그램에서 wait() 메서드를 사용하면 위에 언급 한 시나리오가 암시 적으로 실행됩니다. – UVM

0

아니요, 스레드를 사용하고 있기 때문에 잠금 또는 대기가 필요하지 않습니다. 그러나 스레드가 데이터를 교환하기를 원하면 종종 유용합니다.

다음은 소비자 생산자 모델의 예와 함께 좋은 설명입니다 :

http://www.ase.md/~aursu/JavaThreadsSynchronization.html

건배!

+0

이 링크는 2 가지 방법으로 생산자 소비자의 사용을 보여줍니다. 하나는 yield() 메소드를 사용하고 다른 하나는 정상 대기를 사용하고 통지합니다. 사실, 첫 번째 방법은 위에서 언급 한 매개 변수 참고 :이 링크를 참조하십시오 .http : //www.javamex.com/tutorials/threads/yield.shtml 또한 lock() 연산이 있다면 아직도 yeild를 사용할 수 있습니다. (왜냐하면, 소유권 변경). – UVM

0

블록 : 실행 금지.
대기 : 현재 스레드를 일시 중단합니다.
잠금 : 잠글 때 다른 사람은 사용할 수 없습니다.
고객이 영화 티켓을 구입할 때 온라인 구매를 고려하십시오. 그가 자리를 선택하자 마자. 다른 사람들은 동시에 같은 자리에 앉을 수 없습니다 (그 자리 고정).

+0

pls 내 질문을 이해 – UVM

+0

그건 당신이 시스템에 대해 알고 있다면 당신의 요구 사항에 따라 당신은 스레드와 함께 갈 것인지 아닌지를 결정할 수 있습니다. 더 나은 결과를 얻으려면 시나리오를 확장하는 것이 좋습니다. – special