어떤 경우에는 교착상태를 피할 수 있습니다. 이 기사에서는 교착 상태를 방지하는 세 가지 기술을 설명합니다. Java에서 교착 상태를 방지하는 방법에 대한 지식에 관심이 있는 친구는 이 기사에서 배워야 합니다
어떤 경우에는 교착 상태를 피할 수 있습니다. 이 기사에서는 교착 상태를 방지하는 세 가지 기술을 설명합니다.
2. 잠금 시간 제한
3. 교착 상태 감지
잠금 순서 순서가 다르면 교착 상태가 쉽게 발생할 수 있습니다.
모든 스레드가 동일한 순서로 잠금을 획득하도록 보장할 수 있으면 교착 상태가 발생하지 않습니다. 다음 예를 살펴보십시오.
Thread 1: lock A lock B Thread 2: wait for A lock C (when A locked) Thread 3: wait for A wait for B wait for C
예를 들어 스레드 2와 스레드 3은 잠금 A를 획득한 후에만 잠금 C를 획득하려고 시도할 수 있습니다(잠금 A 획득은 잠금 C를 획득하기 위한 필수 조건입니다). 스레드 1이 이미 잠금 A를 소유하고 있으므로 스레드 2와 3은 잠금 A가 해제될 때까지 기다려야 합니다. 그런 다음 B 또는 C를 잠그기 전에 A를 성공적으로 잠가야 합니다.
순서대로 잠금하는 것은 효과적인 교착 상태 방지 메커니즘입니다. 그러나 이 방법을 사용하려면 사용할 수 있는 모든 잠금을 미리 알아야 하지만(그리고 이러한 잠금의 순서를 적절하게 지정해야 함) 예측할 수 없는 경우도 있습니다.
잠금 시간 제한교착 상태를 피하는 또 다른 방법은 잠금을 획득하려고 할 때 시간 초과를 추가하는 것입니다. 즉, 잠금을 획득하려고 할 때 이 시간 제한을 초과하면 스레드가 해당 스레드를 포기합니다. 잠금 요청. 스레드가 주어진 시간 제한 내에 필요한 모든 잠금을 성공적으로 획득하지 못하면 획득한 모든 잠금을 롤백하고 해제한 다음 다시 시도하기 전에 임의의 시간 동안 기다립니다. 이 무작위 대기 시간은
other스레드에 동일한 잠금을 획득하려고 시도할 수 있는 기회를 제공하고 애플리케이션이 잠금을 획득하지 않고 계속 실행될 수 있도록 합니다(잠금 시간이 초과된 후에도 계속 실행하고 다른 작업을 수행할 수 있음). 뒤로 이전 잠금 논리를 반복합니다. 다음은 서로 다른 순서로 동일한 두 개의 잠금을 획득하려고 시도하고 시간 초과가 발생한 후 롤백하고 다시 시도하는 두 스레드를 보여주는 예입니다.
Thread 1 locks A Thread 2 locks B Thread 1 attempts to lock B but is blocked Thread 2 attempts to lock A but is blocked Thread 1's lock attempt on B times out Thread 1 backs up and releases A as well Thread 1 waits randomly (e.g. 257 millis) before retrying. Thread 2's lock attempt on A times out Thread 2 backs up and releases B as well Thread 2 waits randomly (e.g. 43 millis) before retrying.
에 있습니다. 스레드 2가 종료되면 스레드 1도 이 두 잠금을 성공적으로 획득할 수 있습니다(스레드 1이 두 잠금을 성공적으로 획득하기 전에 스레드 2 또는 다른 스레드가 일부 잠금을 획득하지 않는 한).
잠금 시간 초과로 인해 이 시나리오가 교착 상태라고 생각할 수 없다는 점에 유의해야 합니다. 잠금을 획득한 스레드(다른 스레드의 시간 초과 발생)가 작업을 완료하는 데 오랜 시간이 걸릴 수도 있습니다.
또한 동일한 리소스 배치에 대해 동시에 경쟁하는 스레드가 많은 경우 시간 초과 및 롤백 메커니즘이 있더라도 이러한 스레드는 여전히 반복적으로 시도하지만 잠금을 얻지 못할 수 있습니다. 스레드가 2개만 있고 재시도 시간 초과가 0~500밀리초로 설정된 경우에는 이러한 현상이 발생하지 않을 수 있지만 스레드가 10개 또는 20개인 경우에는 상황이 다릅니다. 이러한 스레드가 동일한 재시도 시간을 기다릴 확률이 훨씬 높기 때문입니다(또는 너무 가까워서 문제가 발생할 수 있음). (타임아웃 및 재시도 메커니즘은 동시에 발생하는 경쟁을 피하기 위한 것입니다. 그러나 스레드가 많은 경우 두 개 이상의 스레드의 타임아웃 시간은 동일하거나 가까울 가능성이 높으므로 경쟁이 발생하더라도 시간 초과가 발생하면 나중에 시간 초과가 동일하기 때문에 동시에 재시도를 시작하여 새로운 경쟁 라운드가 발생하고 새로운 문제가 발생합니다)
이 메커니즘에는 문제가 있습니다. 시간 초과를 설정할 수 없습니다. Java 시간의 동기화된 블록에 대한 것입니다. 사용자 정의 잠금을 생성하거나 Java5의 java.util.con
패키지에 있는 도구를 사용해야 합니다. 사용자 정의 잠금 클래스를 작성하는 것은 복잡하지 않지만 이 기사의 범위를 벗어납니다.
교착 상태 감지교착 상태 감지는 더 나은 교착 상태 방지 메커니즘으로 주로 순차 잠금이 불가능하고 잠금 시간 제한이 불가능한 시나리오를 대상으로 합니다.
스레드가 잠금을 획득할 때마다 스레드 및 잠금 관련 데이터 구조(맵, 그래프 등)에 기록됩니다. 또한 스레드가 잠금을 요청할 때마다 이 데이터 구조에 기록되어야 합니다.
스레드가 잠금 요청에 실패하면 스레드는 잠금 그래프를 순회하여 교착 상태가 발생했는지 확인할 수 있습니다. 예를 들어 스레드 A가 잠금 7을 요청했지만 이때 잠금 7은 스레드 B가 보유하고 있습니다. 이때 스레드 A는 스레드 A가 현재 보유하고 있는 잠금을 스레드 B가 요청했는지 확인할 수 있습니다. 스레드 B가 그러한 요청을 하면 교착 상태가 발생한 것입니다(스레드 A는 잠금 1을 소유하고 잠금 7을 요청하며, 스레드 B는 잠금 7을 소유하고 잠금 1을 요청합니다).
물론 교착 상태는 일반적으로 서로의 잠금을 유지하는 두 스레드보다 더 복잡합니다. 스레드 A는 스레드 B를 기다리고, 스레드 B는 스레드 C를 기다리고, 스레드 C는 스레드 D를 기다리고, 스레드 D는 스레드 A를 기다립니다. 스레드 A가 교착 상태를 감지하려면 B가 요청한 모든 잠금을 점진적으로 감지해야 합니다. 스레드 B가 요청한 잠금부터 시작하여 스레드 A는 스레드 C를 찾은 다음 스레드 D를 발견하고 스레드 D가 요청한 잠금이 스레드 A 자체에 의해 유지되었음을 발견했습니다. 이때 교착 상태가 발생했음을 알 수 있습니다.
그렇다면 교착 상태가 감지되면 이 스레드는 무엇을 해야 할까요?
가능한 접근 방식은 모든 잠금을 해제하고 롤백한 후 다시 시도하기 전에 임의의 시간 동안 기다리는 것입니다. 이는 단순 잠금 시간 초과와 비슷하지만 잠금 요청 시간이 초과되어 롤백이 발생하는 것이 아니라 교착 상태가 발생한 경우에만 롤백이 발생한다는 점이 다릅니다. 백오프 및 대기가 있지만 동일한 잠금 배치를 위해 경쟁하는 스레드 수가 많으면 여전히 교착 상태가 반복적으로 발생합니다.
더 나은 해결책은 이러한 스레드에 대해 우선 순위를 설정하고 하나(또는 몇 개의) 스레드가 롤백되도록 하고 나머지 스레드는 마치 교착 상태가 발생하지 않은 것처럼 필요한 잠금을 계속 유지하는 것입니다. 이러한 스레드에 할당된 우선순위가 고정되어 있으면 동일한 스레드가 항상 더 높은 우선순위를 갖습니다. 이 문제를 방지하려면 교착 상태가 발생할 때 임의의 우선순위를 설정할 수 있습니다.
위 내용은 Java에서 교착 상태를 방지하는 방법에 대한 샘플 코드 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!