24. 두 엔티티 상호작용의 락 획득 순서 (ABBA 데드락)
난이도 최상 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// ============================================================================
// [코드리뷰 문제] C# - 두 엔티티 상호작용의 락 획득 순서
// ----------------------------------------------------------------------------
// 시나리오 (동시성/메모리 · 서버-클라):
// - 두 캐릭터(Entity) 사이의 상호작용을 처리한다. 예: 상호 유대(친밀도) 갱신,
// 서로에게 버프 공유, 1:1 아이템 이전 등 "두 객체의 상태를 함께" 바꿔야 하는 작업.
// - 정합성을 위해 두 엔티티를 모두 잠근 뒤 상태를 갱신한다.
// - 같은 두 캐릭터 사이에 상호작용이 "양방향으로 동시에" 일어날 수 있다:
// 스레드1 이 Link(x, y), 스레드2 가 Link(y, x) 를 동시에 호출.
//
// 요구사항:
// - 두 엔티티의 상태는 원자적으로(둘 다 잠근 상태에서) 갱신돼야 한다.
// - 어떤 순서/방향으로 동시에 호출돼도 서버가 멈추지 않고 진행돼야 한다.
// - 같은 엔티티끼리(자기 자신) 호출돼도 안전해야 한다.
//
// 과제:
// 이 코드의 잠재적 문제를 모두 찾고, 양방향 동시 호출에서 어떤 일이 벌어지는지
// 설명하고, 수정안과 더 나은 설계를 제시하라.
// (먼저 직접 리뷰를 적은 뒤 answer.md 와 대조할 것)
// ============================================================================
public class Entity
{
public long Id;
public readonly object Lock = new();
public int Bond; // 예시 상태
}
public class BondService
{
public void Link(Entity a, Entity b)
{
lock (a.Lock) // (A)
{
DoSomeWork(); // 두 락 사이의 약간의 작업(경합 창을 넓힘)
lock (b.Lock) // (B)
{
a.Bond++;
b.Bond++;
}
}
}
private void DoSomeWork()
{
// 상태 검증/로깅 등(생략)
}
} 결함 코드 · C++
// ============================================================================
// [코드리뷰 문제] C++ - 두 엔티티 상호작용의 락 획득 순서
// ----------------------------------------------------------------------------
// 시나리오 (동시성/메모리 · 서버-클라):
// - 두 캐릭터(Entity) 사이의 상호작용을 처리한다. 예: 상호 유대 갱신, 버프 공유,
// 1:1 아이템 이전 등 "두 객체의 상태를 함께" 바꿔야 하는 작업.
// - 정합성을 위해 두 엔티티를 모두 잠근 뒤 상태를 갱신한다.
// - 같은 두 캐릭터 사이에 상호작용이 "양방향으로 동시에" 일어날 수 있다:
// 스레드1 이 Link(x, y), 스레드2 가 Link(y, x) 를 동시에 호출.
//
// 요구사항:
// - 두 엔티티의 상태는 둘 다 잠근 상태에서 원자적으로 갱신돼야 한다.
// - 어떤 순서/방향으로 동시에 호출돼도 서버가 멈추지 않고 진행돼야 한다.
// - 같은 엔티티끼리(자기 자신) 호출돼도 안전해야 한다.
//
// 과제:
// 이 코드의 잠재적 문제를 모두 찾고, 양방향 동시 호출과 자기 자신 호출에서 무엇이
// 벌어지는지 설명하고, 수정안과 더 나은 설계를 제시하라.
// (먼저 직접 리뷰를 적은 뒤 answer.md 와 대조할 것)
// ============================================================================
#include <mutex>
#include <cstdint>
struct Entity
{
int64_t id;
std::mutex m;
int bond = 0;
};
class BondService
{
public:
void Link(Entity& a, Entity& b)
{
std::lock_guard<std::mutex> la(a.m); // (A)
DoSomeWork(); // 두 락 사이의 작업(경합 창)
std::lock_guard<std::mutex> lb(b.m); // (B)
a.bond++;
b.bond++;
}
private:
void DoSomeWork() {}
}; 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.
내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.