Why Are Thread.stop, Thread.suspend,Thread.번역판
9136 단어 다중 스레드
천성적으로 안전하지 않기 때문이다.스레드를 중지하면 스레드에 잠긴 모든 모니터의 잠금이 해제됩니다(모니터는 스택 상단에서 ThreadDeath 예외가 발생하는 방식으로 잠금이 해제됩니다).만약 이전에 이 모니터에 의해 보호된 모든 대상이 일치하지 않는 상태에 있었다면 다른 라인에서 본 대상들은 일치하지 않는 상태에 있을 것이다.이런 대상을 손상(damaged)이라고 부른다.라인이 손상된 대상에서 조작을 진행할 때 임의의 행위를 초래할 수 있다.이런 행위는 미묘하고 검측하기 어려울 수도 있고 비교적 뚜렷할 수도 있다.다른 검출되지 않은 (unchecked) 이상과 달리 Thread Death는 소리 없이 죽이고 다른 라인을 죽였다.따라서 사용자는 프로그램이 붕괴될 수도 있다는 경고를 받지 못한다.붕괴는 진정한 파괴가 발생한 후 임의의 시간에 나타나며, 심지어는 몇 시간 또는 며칠 뒤에 나타난다.
설마 내가 ThreadDeath 이상만 포획해서 손상 대상을 수정할 수 없단 말인가?
이론적으로는 가능할지 모르지만, 정확한 다중 루틴 코드를 쓰는 작업은 매우 복잡할 것이다.두 가지 이유로 이 임무는 거의 완성할 수 없을 것이다.
1. 스레드는 거의 모든 곳에서 ThreadDeath 이상을 던질 수 있다.이 점 때문에 모든 동기화 방법과 블록은 대소를 가리지 않고 고려되어야 한다.
2. 라인이 첫 번째 Thread Death 이상을 제거할 때(catch나finally 문장에서) 두 번째 라인을 던질 수 있습니다.정리 작업은 성공할 때까지 반복해야만 할 것이다.이 점을 보장하는 코드는 매우 복잡할 것이다.
Thread.stop(Throwable)에는 어떤 문제가 있습니까?
상술한 모든 문제를 제외하고 이 방법은 목표 라인이 처리할 준비가 되지 않은 이상을 일으킬 수 있다(이 방법을 실현하기 위해 라인이 던질 수 없는 검사를 받는 이상을 포함한다).예를 들어 다음 방법 동작은 자바의throw 동작과 같지만 컴파일러의 노력을 돌려서 호출할 방법이 던질 수 있는 모든 이상을 성명했음을 보장합니다.
static void sneakyThrow(Throwable t) {
Thread.currentThread().stop(t);
나는 무엇으로 Thread를 대체해야 합니까?stop ?
대부분의 stop의 사용은 목표 라인이 정지될 것을 표시하기 위해 간단하게 변수를 수정하는 코드로 바뀌어야 한다.목표 라인은 반드시 규칙적으로 이 변수들을 검사해야 한다.또한, 이 변수가 실행을 중지할 것을 표시하면, 목표 루틴은 일정한 질서정연한 방식으로 루틴 방법에서 되돌아와야 한다. (이것이 바로 Java Tutorial이 일관되게 제안한 방식이다.)요청이 제때에 전달되지 않도록 하기 위해서 변수는volatile(또는 변수의 접근이 동기화되어야 한다).
예를 들어, 애플릿에 start, stop 및run 메서드가 포함되어 있다고 가정합니다.
private Thread blinker;
public void start() {
blinker = new Thread(this);
blinker.start();
}
public void stop() {
blinker.stop(); // UNSAFE!
}
public void run() {
Thread thisThread = Thread.currentThread();
while (true) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
Thread 사용을 피하기 위해서.stop, 애플릿의 stop과run 방법을 다음과 같이 바꿀 수 있습니다.
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
나는 어떻게 해야만 장시간 기다리는 라인을 멈출 수 있습니까? (예를 들어 입력에 사용)
이것이 바로 Thread입니다.interrupt 방법이 할 거야.상기와 같은'상태 기반'의 신호 전달 메커니즘은 응용될 수 있지만 상태 전달(blinker=null, 이전 예에서) 뒤에는 Thread가 있을 수 있다.인터럽트 및 대기 중 사용을 위한 interrupt 호출:
public void stop() {
Thread moribund = waiter;
waiter = null;
moribund.interrupt();
}
이런 기술이 작용하기 위해서는 중단된 이상을 포획했지만 즉각 처리할 준비가 되지 않은 어떤 방법에도 이상을 재단언해야 한다는 것이 관건이다.다시 던지기 (rethorws) 가 아니라 다시 단언하기 (reasserts) 라고 합니다. 이상을 다시 던지는 것이 항상 가능한 것은 아니기 때문입니다.InterruptedException을 캡처하는 방법이 이러한 (검사) 이상을 던진 것으로 선언되지 않았다면, 다음 주문을 사용해서 '자신을 다시 중단해야 한다'.
Thread.currentThread().interrupt();
스레드가 Thread에 응답하지 않으면인터럽트는 어떻게 되나요?
어떤 경우, 너는 특정한 응용 기교를 채택할 수 있다.예를 들어, 만약 루틴이 이미 알고 있는 socket에서 기다린다면, 이 socket을 닫아서 루틴이 즉시 되돌아오도록 할 수 있습니다.불행히도 사방에 널리 퍼져 일할 수 있는 통용 기술이 없다.대기 스레드에 대해 Thread가 응답하지 않음을 주의해야 합니다.interrupt의 모든 상황은 Thread에 응답하지 않습니다.stop . 이러한 사례는 의도적인 서비스 공격 거부와thread를 포함한다.stop과thread.interrupt에서 제대로 작동하지 않는 입출력 작업입니다.
왜 Thread?suspend와 Thread.resume가 폐기됐어요?
Thread.suspend는 천성적으로 자물쇠가 사라지기 쉽다.만약 목표 라인이 끊겼을 때 시스템의 관건적인 자원을 보호하는 모니터에 자물쇠를 가지고 있다면 다른 라인은 목표 라인이 복구되기 전에 이 자원에 접근할 수 없습니다.목표 라인의 라인을 복구하려면resume를 호출하기 전에 이 모니터를 잠그려고 하면 잠금이 사라집니다.이런 자물쇠는 일반적으로 자체적으로 동결(frozen) 프로세스로 나타난다.
나는 무엇으로 Thread를 대체해야 합니까?suspend와 Thread.resume ?
및 Thread.stop, 유사하고 신중한 방식은 '목표 스레드' 가 스레드의 기대 상태 (활동 또는 끊기) 를 표시하는 변수를 돌아가게 하는 것이다.예상 상태가 끊겼을 때, 라인은 Object를 사용합니다.wait 기다리기;복원할 때 Object를 사용합니다.notify에서 목표 라인을 알립니다.
예를 들어, 당신의 applet에 아래의mousePressed 이벤트 핸들이 포함되어 있다고 가정하면, blinker라고 불리는 라인의 상태를 전환할 수 있습니다.
private boolean threadSuspended;
Public void mousePressed(MouseEvent e) {
e.consume();
if (threadSuspended)
blinker.resume();
else
blinker.suspend(); // DEADLOCK-PRONE!
threadSuspended = !threadSuspended;
}
Thread를 사용하지 마십시오.suspend와 Thread.resume, 당신은 상술한 이벤트 핸들을 다음과 같이 바꿀 수 있습니다.
public synchronized void mousePressed(MouseEvent e) {
e.consume();
threadSuspended = !threadSuspended;
if (!threadSuspended)
notify();
}
다음 코드를 실행 주기에 추가합니다.
synchronized(this) {
while (threadSuspended)
wait();
}
wait 방법은InterruptedException을 던지기 때문에 "try...catch"문장에 있어야 합니다.sleep 방법을 사용할 때도 같은 문장에 넣을 수 있습니다.검사는 라인이 복구될 때 창이 바로 다시 그려져야 합니다.수정된 run 방법은 다음과 같습니다.
public void run() {
while (true) {
try {
Thread.currentThread().sleep(interval);
synchronized(this) {
while (threadSuspended)
wait();
}
} catch (InterruptedException e){
}
repaint();
}
}
mousePressed 방법의 Notify와run 방법의 wait는synchronized 문장 블록에 있습니다.이것은 언어의 요구이며,wait와 notify가 정확하게 직렬화되어 실행될 수 있도록 보장합니다.실제 효과로 볼 때, 이것은 경쟁 조건을 없애고, 불확실한 '마운트' 라인이 notify 메시지를 잃어버려도 마운트를 유지하는 것을 피할 수 있다.
플랫폼의 성숙한 자바의 동기화 비용이 줄어들고 있지만 영원히 공짜는 아니다.우리가 '운행 순환' 에 가입할 때마다 동기화되는 것을 제거하는 간단한 방법이 있다.추가된 동기화 블록은 약간 복잡한 코드 세션으로 대체되며, 라인이 진정으로 끊겼을 때만 동기화 블록에 들어갈 수 있습니다.
if (threadSuspended) {
synchronized(this) {
while (threadSuspended)
wait();
}
}
명시적 동기화가 부족하기 때문에threadSuspended는volatile로 지정되어 마운트 요청이 신속하게 전달될 수 있도록 해야 합니다.수정된 run 방법은 다음과 같습니다.
private boolean volatile threadSuspended;
public void run() {
while (true) {
try {
Thread.currentThread().sleep(interval);
if (threadSuspended) {
synchronized(this) {
while (threadSuspended)
wait();
}
}
} catch (InterruptedException e){
}
repaint();
}
}
나는 두 가지 기술을 결합시켜 안전하게 '정지' 또는 '끊기' 할 수 있는 라인을 만들 수 있습니까?
네, 이것은 상당히 직관적입니다.목표 라인이 이미 끊어졌을 때, 다른 라인이 그것을 멈추려고 시도하는 것을 알아차리기 어려운 부분이 있다.만약 stop 방법이 상태 변수 (blinker) 를null로 설정한다면, 목표 라인은 우아하게 종료되는 것이 아니라, 마운트 상태 (대기 모니터) 에 있을 것입니다.애플릿이 다시 시작되면 여러 라인이 모니터에서 기다리는 것을 동시에 끝내서 이상한 행동을 할 수 있습니다.
이런 상황을 교정하기 위해서 stop 방법은 반드시 걸린 목표 라인의 신속한 회복을 보장해야 한다.일단 목표의 라인이 회복되면, 목표가 멈췄다는 것을 즉각 깨닫고 우아하게 물러나야 한다.수정된 런 및 stop 방법:
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval);
synchronized(this) {
while (threadSuspended && blinker==thisThread)
wait();
}
} catch (InterruptedException e){
}
repaint();
}
}
public synchronized void stop() {
blinker = null;
notify();
}
만약 stop 방법이 Thread를 호출한다면.interrupt, 앞에서 말한 바와 같이, 그것도 notify를 호출할 필요가 없지만, 그는 여전히 동기화되어야 한다.따라서 경쟁 조건 때문에 타겟 스레드가 중단되지 않습니다.
Thread 정보.destroy 어때요?
Thread.Destroy는 실현된 적이 없습니다.만약 그것이 실현된다면, 그것은 Thread와 함께 될 것이다.suspend처럼 잠기기 쉽다. (사실상, 그것은 대체로 후속 Thread.resume가 없는 Thread.suspend와 같다.)우리는 지금 그것을 실현하지도, 폐지하지도 않았다.비록 그것은 확실히 사라진 자물쇠가 발생하기 쉽지만, 어떤 사람들은 프로그램이 직접 퇴출하지 않고 사라진 자물쇠의 위험을 무릅쓰기를 원할 수도 있다고 논쟁한 적이 있다.
왜 런타임이야?run Finalizers On Exit가 폐기되었습니까?
천성적으로 안전하지 않기 때문이다.이것은 종결기 (finallizers) 가 활동 대상에서 호출되고, 다른 라인이 이 대상을 병렬적으로 조작하여 이상한 행동이나 잠금을 일으킬 수 있습니다.그러나 종결 대상의 클래스가 '방어' 로 인코딩되고 있다면 이 문제는 피할 수 있습니다.대부분의 프로그래머들은 그것을 막지 않을 것이다.그것들은 종결기가 호출되었을 때 대상의 대상이 이미 죽었다고 가정한다.
그리고 이 호출은'스레드 안전'이 아니다. 왜냐하면 이것은 VM 전역 로고를 설정했기 때문이다.이것은 모든 종결기를 가진 종류의 방어 활동 대상의 종결을 강요한다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Java 다중 스레드를 순차적으로 실행하는 몇 가지 방법 요약Java 다중 스레드를 순차적으로 실행하는 몇 가지 방법 요약 동료는 무심결에 이 문제를 제기하고 두 가지 방법을 직접 실천했다.물론 더 좋은 방법이 있을 거야. 방법 1 이런 방법은 비교적 흔히 볼 수 있는 해결 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.