void transfer(Account from,Account to,int money){ from.setAmount(from.getAmount()-money); to.setAmount(to.getAmount()+money); }
단일 스레드에서 , 이 코드는 확실히 문제가 없지만 멀티스레딩에 문제가 있습니다
이제 추가해 보세요. 잠금, 잠금 후의 코드는 다음과 같습니다
void transfer(Account from,Account to,int money){ synchronized(from){ synchronized(to){ from.setAmount(from.getAmount()-money); to.setAmount(to.getAmount()+money); } } }
synchronized, 즉 , 객체 잠금, 첫 번째 동기화는 from 객체를 잠그고 두 번째 동기화는 to 객체를 잠급니다.
멀티스레딩의 경우 여러 스레드 중 하나의 스레드만 동시에 이 객체 잠금을 획득하고 객체 잠금에서 코드 세그먼트를 작동할 수 있습니다
하지만 추가 개체 잠금을 얻은 후 교착 상태가 발생할 수 있습니다!
transfer(a,b,100)과 transfer(b,a,100)이 동시에 수행됩니다. 즉, a가 b에게 돈을 이체하는 동안 b도 a에게 돈을 이체합니다# 🎜🎜#
【1】a가 b에게 돈을 이체하고, 스레드 1] 이체 작업을 수행하기 위해 객체 잠금 b가 긴급하게 필요합니다 작업 [2] 객체 잠금 A가 긴급하게 필요합니다 전송 작업을 수행하려면 두 스레드가 모두 대기 중입니다. 그룹의 다른 스레드가 잠금을 해제하고 교착 상태가 발생합니다! 2. 교착상태 해결어디부터 시작해야 할까요? 【1】상호 배제 대기 깨기 일반적으로 프로그램의 안전을 위해 객체를 잠가야 하므로 이 조건은 일반적으로 깨질 수 없습니다【2】Break Hold and Wait, 즉 소유 대기 샘플 코드에서는 from과 to 두 리소스를 동시에 얻을 수 없습니다. 시간이지만 배포를 통해 얻습니다. 방법 1: to에 짧은 시간 초과를 추가합니다. 획득 시도가 시간 초과되면 처음에 보류했던 잠금을 즉시 해제합니다.
#🎜🎜 #다시 시도하세요. from 및 to 잠금을 획득합니다. 권장되는 방법입니다
방법 2: 전송 작업이 완료된 후 전역 잠금이 해제되도록 이 코드에 전역 잠금을 추가합니다. 비교적 안전하지만 은행 계좌가 많고 이체 작업이 매우 빈번합니다. 이 방법을 사용하면 필연적으로 성능이 크게 저하됩니다.
[3] Break the loop wait
#🎜 🎜# 순서대로 리소스를 확보하고 계정 ID 크기에 따라 이전 작업을 수행합니다. ID가 작은 계정은 먼저 이전 작업을 수행하고 ID가 큰 계정은 나중에 이전 작업을 수행합니다. 그러나 실제 생활에서는 ID가 없는 것, 즉 순서가 없는 것들도 있습니다. 이때 강제로 명령을 내릴 필요가 있습니다. 【4】돌이킬 수 없는 기다림을 깨세요 시간 제한을 추가하는 것은 최후의 수단입니다. 사용자의 전송 작업이 실패하고 사용자 경험이 좋지 않습니다#🎜 🎜# 개인적으로 추천하는 해결 방법:
사용자의 짧은 대기 시간을 희생하고 [2]의 방법 1을 사용
관련 기사:
# 🎜🎜#The Java의 교착 상태 개념 및 해결 방법
교착 상태의 개념과 교착 상태의 조건
위 내용은 [JAVA] 교착상태 발생과 해결 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!