Skip to content

[사전과제] 동시성 제어#16

Open
bmsnc wants to merge 4 commits intohanghae-skillup:mainfrom
bmsnc:redis_pre
Open

[사전과제] 동시성 제어#16
bmsnc wants to merge 4 commits intohanghae-skillup:mainfrom
bmsnc:redis_pre

Conversation

@bmsnc
Copy link

@bmsnc bmsnc commented Jan 5, 2025

동시성 제어

[사전과제] 동시성 제어


작업 내용

productDatabase 전역 변수의 자료 구조 수정

  • private final Map<String, Integer> productDatabase = new HashMap<>(); (변경 전)
  • private final Map<String, Integer> productDatabase = new ConcurrentHashMap<>(); (변경 후)

productDatabase key 값이 같다면 thread-safe 하게 재고 조회 - 업데이트 할 수 있도록 수정

public void order(String productName, int amount) {
    productDatabase.compute(productName, (key, currentStock) -> {
        if (currentStock == null) {
            currentStock = 0; // 기본값
        }

        try {
            Thread.sleep(1); // 동시성 이슈 유발을 위한 인위적 지연
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }

        String name;
        if (currentStock >= amount) {
            name = Thread.currentThread().getName().split("-")[3];
            System.out.println("Thread " + name + " 주문 정보: " + productName + ": 1건 ([" + amount + "])");
            latestOrderDatabase.put(productName, new OrderInfo(productName, amount, System.currentTimeMillis()));

            return currentStock - amount; // 업데이트된 재고 반환
        } else {
            return currentStock; // 재고가 부족하면 변경하지 않음
        }
    });
}
        try {
            Thread.sleep(1); // 동시성 이슈 유발을 위한 인위적 지연
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }

        String name;
        if (currentStock >= amount) {
            name = Thread.currentThread().getName().split("-")[3];
            System.out.println("Thread " + name + " 주문 정보: " + productName + ": 1건 ([" + amount + "])");
            latestOrderDatabase.put(productName, new OrderInfo(productName, amount, System.currentTimeMillis()));

            return currentStock - amount; // 업데이트된 재고 반환
        } else {
            return currentStock; // 재고가 부족하면 변경하지 않음
        }
    });
}

발생했던 문제와 해결 과정을 남겨 주세요.

문제 1 : 재고 조회와 수량 변경이 작업별로 순차적으로 이루어지지 않아 데이터 정합성을 보장하지 못함
해결 방법 1 : 동시성 문제를 해결할 수 있는 ConcurrentHashMap 자료 구조 활용

  • ConcurrentHashMap의 compute 함수를 활용해 key 값에 대한 value를 thread - safe 하도록 변경

이번 주차에서 고민되었던 지점이나, 어려웠던 점을 알려 주세요.

동시성 이라는 문제에 대해 해결해 본적이 없어 제공해 주신 자료를 통해 어떻게 해결해야 할 지 감을 잡을 수 있었습니다.

  • 제가 작성한 코드는 단순히 전역변수로 관리되는 productDatabase의 동시성 문제를 해결했다고 생각합니다. 실무에서도 이런 방식을 채택해서 사용하는지 ? 그렇다면, repository 단의 전역변수를 동시성 문제를 해결하려면 어떻게 코드를 작성해야 하는지 궁급합니다.

리뷰 포인트

동시성 문제를 해결하는 방법으로 크게 1. synchronized, 2. ConcurrentHashMap, 3. Queue 를 활용한 순착적인 제어
이렇게 3가지가 있다는 것을 알았습니다. 실무에서 일반적으로 사용하는 방식 혹은 상황에 맞게 채택하는 기준에 대해 설명해 주시면 좋을 거 같습니다 ! 또, 추가적으로 제가 알지 못하는 방법도 있다면 설명해 주셨으면 좋겠습니다 ! 감사합니다 !

기타 질문

public void order(String productName, int amount) {
    Integer currentStock = productDatabase.getOrDefault(productName, 0);

    try {
        Thread.sleep(1); // 동시성 이슈 유발을 위한 인위적 지연
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new RuntimeException(e);
    }

    if (currentStock >= amount) {
        productDatabase.put(productName, currentStock - amount);
        latestOrderDatabase.put(productName, new OrderInfo(productName, amount, System.currentTimeMillis()));
        System.out.println("latestOrderDatabase = " + latestOrderDatabase);
    }
}
  • 해당 코드는 System.out.println("latestOrderDatabase = " + latestOrderDatabase); 이 부분만 latestOrderDatabase.put() 이후에 추가했을 뿐인데 테스트 결과에 영향을 주고 있습니다. 동시성 문제가 해결된 것 같지는 않지만 결과는 기대 수량과 잔여 수량이 일치하고 있습니다.
    왜 이런 결과가 나왔는지 궁급합니다 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant