동시성 문제 수정 – 동기화됨(2)

동시성 문제는 무엇입니까? – (하나)

내가 이 글을 쓰는 이유는? CS와 Java를 공부하면서 동시성에 대한 많은 언급이 있었습니다.

이 부분은 개념적으로 이해했지만 실제로는 코드를 통해 배웠고

pos04167.tistory.com

이전 기사에서는 동시성 문제에 대해 논의했으며 이번에는 이러한 문제를 해결하는 방법에 대해 배운 내용을 요약했습니다.

동시성 문제만 생각하면 데이터 접근 스레드가 여러 개 있고 데이터 무결성 문제가 있다는 것을 이해해야 하는데, 이 문제를 해결하려면 단순하게 생각하면 데이터 접근 스레드가 한 개뿐이라는 문제가 있다.

그럼 Synchronized by Java를 통해 어떻게 해결하는지 알아보겠습니다.

해결책을 설명하고 설명하면

1. 기존 서비스에 대한 @Transactional삭제하고 동기화하여 추가합니다.

@Service
@RequiredArgsConstructor
public class StockService {

    private final StockRepository stockRepository;

    @Transactional
    public synchronized   void decrease(Long id , Long quantity){
        Stock stock = stockRepository.findById(id)
                .orElseThrow();

        stock.decrease(quantity);

        stockRepository.saveAndFlush(stock);
    }

}

2. 테스트 케이스를 확인한 후 성공 여부를 확인할 수 있습니다.

@Test
@DisplayName("멀티스레드 환경 테스트")
public void decreaseWithMultiThreadInvalid() throws Exception {
    int threadCount = 100;
    ExecutorService executorService = Executors.newFixedThreadPool(32);//비동기 작업을 도와준다.

CountDownLatch downLatch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { executorService.submit(() -> { try { service.decrease(1L, 1L); } finally { downLatch.countDown(); } }); } downLatch.await(); Stock stock = stockRepository.findById(1L) .orElseThrow(); assertEquals(0L, stock.getQuantity()); }


그렇다면 동기화 및 트랜잭션 솔루션을 통해 이 문제를 해결할 수 있는 이유는 무엇입니까?

1. 동기화

  • synced 키워드는 동기화 범위를 나타내는 데 사용됩니다.

    여기서는 동기화를 예로 들어 설명하는데, 쓰레드 간에 공유 및 수정이 가능한 데이터를 동기화 없이 함께 사용할 경우 데이터 일관성이 떨어지는 문제가 발생한다.

  • 따라서 동기화를 통해 스레드로부터 안전한 환경을 만들어야 합니다.

    synced 키워드를 사용하면 현재 데이터에 액세스하고 있는 스레드가 아닌 다른 스레드가 데이터에 액세스할 수 없습니다.

그렇다면 동기화를 사용하여 스레드로부터 안전하게 만드는 것이 좋지 않습니까?

그렇게 생각할 수 있지만 프로그램 성능 저하로 이어질 가능성이 높습니다.

이는 Synchronized를 사용할 때 블록과 비블록이 내부적으로 생성되고 이러한 프로세스 중 너무 많은 프로세스가 성능 문제를 경험하기 때문입니다.

자주 동기화 사용처

1. 인스턴스 메소드

2. 정적 메서드

3. 인스턴스 메서드 코드 블록

4. 일반적으로 정적 메서드의 코드 블록에서 사용됩니다.

나중에 동기화된 항목에 대해 정리하고 블로그에 올릴 것입니다.

다시 말해서. 여기까지 요약하자면 서로 다른 스레드에 의한 액세스 문제가 동기화에 의해 방지되었다는 것을 아는 것이 좋습니다.

2. 트랜잭션

~ 위에 동기화 및 트랜잭션에 대한 설명이 궁금합니다.

Synchronized를 통해 스레드로부터 안전한 환경을 만들었는데 왜 트랜잭션을 제거해야 하나요? 나는 그것을 상상할 수 있습니다

거래에 대해 조금만 생각해보십시오. 트랜잭션은 기존 클래스를 매핑하여 새 트랜잭션을 생성하여 실행됩니다.

그런 다음 @Transactional을 추가하지 않고 직접 빌드하여 생각합니다.

public void decrease2(Long id, Long quantity) {
    transactional.start()
    Stock stock = stockRepository.findById(id)
            .orElseThrow();

    stock.decrease(quantity);

    transactional.commit();
}

이것이 트랜잭션이 시작되고 커밋되는 방식입니다(설명을 위해 작성됨).

이때 commit() 부분에서 문제가 발생하는데, 동시성 문제는 downdown()과 commit() 사이에 다른 쓰레드가 데이터에 접근하지 못하게 함으로써 해결할 수 있다.

한편 다른 스레드가 데이터에 액세스하여 일관성 문제를 일으킬 수 있습니다.

거래는 아래 포스팅을 참고하시면 좋을 것 같습니다.

(Linux) Linux + 기본 명령어 알아보기

리눅스를 처음 알게 된 건 어렸을 때 영화에서 해커를 보고 검은 화면에 영어가 금세 떴을 때였다.

그 후 컴퓨터 학교에서 리눅스에 대해 배웠고,

pos04167.tistory.com

동시성 문제가 그렇게 쉽게 해결되었습니까?

동기화 문제가 있습니다.

Java 동기화는 프로세스 내에서만 보장됩니다.

다시 말해서. 서버가 1대로 운영되는 것은 상관없지만 서버가 n개로 늘어나면 1대 이상이 데이터에 접근할 수 있다.


위의 이미지를 보면 Server 1이 데이터에 접근할 수 있고 Server 2가 다시 데이터에 접근할 수 있음을 알 수 있습니다.

이렇게 동기화를 사용하면 하나의 서버에서 경쟁 조건을 해결할 수 있지만 여러 서버가 있는 경우 경쟁 조건 문제가 발생하는 것을 볼 수 있습니다.

error: Alert: Content selection is disabled!!