2011-11-02 3 views
0

두 개의 잠금 인 inventoryLock 및 currencyLock을 가진 객체 User가 있습니다. 종종 이러한 잠금은 개별적으로 사용됩니다 (예 : 쉽게 교착 상태를 피하는 방법은 무엇입니까?

synchronized (user.currencyLock) { 

if (user.money < loss) throw new Exception(); 
user.money -= loss; 

} 

그러나

synchronized (user.inventoryLock) { 

// swap items 
tmp = user.inventory[x]; 
user.inventory[x] = user.inventory[y]; 
user.inventory[y] = tmp; 

} 

또는

때때로 코드 조각이 모두 잠금 장치가 필요합니다

synchronized (user.currencyLock) { 
synchronized (user.inventoryLock) { 

    if (user.money < item.price) throw new Exception(); 
    user.money -= item.price; 
    user.inventory[empty] = item; 

} 
} 

간단한 보인다, 그러나 단지이 예보다 모두 잠금 장치를 사용하여 코드의 더 많은 비트가, 이전 경험에서 알 수 있듯이 여러 개의 코드에 동일한 공유 잠금이 필요한 경우 교착 상태가 발생할 위험이 있습니다.

이를 피하는 좋은 방법은 무엇입니까?

두 개체에 원자 적으로 잠글 수있는 메커니즘이 있습니까?

+0

코드에 심각한 캡슐화가 없음을 보여줍니다. 방법을 거치지 않고 사용자의 상태에 직접 액세스합니다. 상태를 클래스에 캡슐화하여 동기화를 중앙 집중화하고 필요한 모든 동기화가 완료되었는지 확인해야합니다. User 클래스 자체에서이 서비스를 제공하는 대신 사용자의 모든 클라이언트가 올바르게 동기화되도록해야합니다. –

+0

@JBNizet 이것은 예제 코드 일뿐입니다. 실제 코드는 사용자 클래스가 수행 할 수없는 데이터베이스 호출을 포함합니다. –

답변

0

이 질문을 게시 한 직후 간단한 해결책을 생각해 냈습니다. 모든 코드가 동일한 순서로 잠금을 획득하는지 확인하십시오. 그런 식으로 두 개의 스레드가 둘 중 하나를 가질 수 없습니다.

자연 순서가 없으면 알파벳순으로 충분하고 기억하기 쉽습니다. 당신은 당신이 inventoryLock을 고정하기 전에 항상 currencyLock을 잠글 것을 보장하고 currencyLock을 잠금을 시도 할 수 없다 경우

3

항상 다른 전에 하나의 잠금 장치는, 교착 상태의 요구 사항 중 하나는, 예를 들어 원형 대기 패턴

입니다 inventoryLock을 이미 가지고있을 때 당신은 괜찮을 것입니다.

+0

이것 역시 제가 생각해 낸 것입니다. 그래서 도움을 줄 수는 있지만 동의하지는 못합니다. –

+0

하나를 다른 것보다 먼저 잠글 수 없습니다. * 항상 같은 순서로 잠금을 획득해야합니다. * – EJP

0

여기에 어떤 circular wait 가능성이 보이지 않습니다. 이것은 데드락에 필요한 4 가지 조건 중 하나입니다.

+0

게시 한 예문뿐만 아니라 두 가지 잠금을 필요로하는 코드가 더 있습니다. 나는 그것을 분명히 할 것이다. –

관련 문제