스프링/스프링 핵심 원리 - 고급편

12. 동시성 문제 예시

sdafdq 2024. 1. 14. 19:54

한 필드에 대해 처리하고 있는데, 중간에 다른 쓰레드가 같은 필드에 대해 처리하게 되면, 

둘이 처리가 겹쳐서 결과적으로 원하는 결과가 나오지 않게 된다.

 

 

테스트

@Slf4j
public class FieldService {
    private String nameStore;

    public String logic(String name){
        log.info("저장 name={} -> nameStore={}", name, nameStore);
        nameStore = name;
        sleep(1000);
        log.info("조회 nameStore={}", nameStore);
        return nameStore;
    }

    private void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

그냥 필드에 저장하고 로그 찍는거.

 

 

@Test
void field(){
    log.info("main start");

    Runnable userA = ()->{
        fieldService.logic("userA");
    };

    Runnable userB = ()->{
        fieldService.logic("userB");
    };

    Thread threadA = new Thread(userA);
    threadA.setName("thread-A");
    Thread threadB = new Thread(userB);
    threadB.setName("thread-B");

    threadA.start();
    sleep(2000);
    threadB.start();
    sleep(2000);
}

저걸 테스트에서 호출하여 사용.

 

Runnable 저게 멀티 쓰레드 인데,

 

Runnable에 저렇게 로직을 저장해 놨다가,

 

Tread 객체 안에 넣어 놓은 다음, (이것저것 쓰레드에 대한 설정도 할 수 있고,)

 

start하면 실행이 된다.

 

logic은 sleep을 1000으로 해 놔서 저렇게 넣넣하게 2000 하면 순서대로 잘 실행이 되는데, 

 

 

 

threadA.start();
sleep(100);
threadB.start();
sleep(2000);

이렇게 시간을 짧게 1000 이내로 바꾸면

 

보면 이렇게 A, 즉 userA 시작했다가, 1000(1초) 되기도 전에 다음 쓰레드 userB 시작해 버려서

필드를 userB로 저장시키고, 결국 userA 쓰레드나 userB 쓰레드나 저장은 

threadA 시작 (즉 필드에 userA 저장)

 

1초 슬립 (동시에 메인 쓰레드는 계속 진행중. 멀티 쓰레드 기 때문. 0.1초 뒤에 threadB 시작. 즉, 아직 0.9초 남아있는 상태에서 필드에 userB로 저장됨)

 

그 후 0.9초가 흐르고 

 

둘 다 userB로 나옴.

 

 

'스프링 > 스프링 핵심 원리 - 고급편' 카테고리의 다른 글

14. 쓰레드로컬 예시  (0) 2024.01.14
13. 쓰레드 로컬 소개  (0) 2024.01.14
11. 동시성 문제  (0) 2024.01.14
10. 필드 동기화 적용  (0) 2024.01.14
9. 필드 동기화  (0) 2024.01.14