목차
동시성 이슈 발생
여러 Thread가 동시에 Application 로직을 호출하게 되면서 Level 상태값이 꼬여서 보이게 된다.

Thread 로 구분해서 로그 확인
2021-12-06 02:18:26.028  INFO 22044 --- [nio-8080-exec-1] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] OrderController.request() 2021-12-06 02:18:26.029  INFO 22044 --- [nio-8080-exec-1] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] |-->OrderService.orderItem() 2021-12-06 02:18:26.029  INFO 22044 --- [nio-8080-exec-1] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] |   |-->OrderRepository.save() 2021-12-06 02:18:27.033  INFO 22044 --- [nio-8080-exec-1] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] |   |<--OrderRepository.save() time=1004ms 2021-12-06 02:18:27.033  INFO 22044 --- [nio-8080-exec-1] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] |<--OrderService.orderItem() time=1004ms 2021-12-06 02:18:27.033  INFO 22044 --- [nio-8080-exec-1] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] OrderController.request() time=1005ms
   | 
 
2021-12-06 02:18:26.114  INFO 22044 --- [nio-8080-exec-2] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] |   |   |-->OrderController.request() 2021-12-06 02:18:26.115  INFO 22044 --- [nio-8080-exec-2] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] |   |   |   |-->OrderService.orderItem() 2021-12-06 02:18:26.115  INFO 22044 --- [nio-8080-exec-2] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] |   |   |   |   |-->OrderRepository.save() 2021-12-06 02:18:27.119  INFO 22044 --- [nio-8080-exec-2] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] |   |   |   |   |<--OrderRepository.save() time=1004ms 2021-12-06 02:18:27.120  INFO 22044 --- [nio-8080-exec-2] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] |   |   |   |<--OrderService.orderItem() time=1005ms 2021-12-06 02:18:27.120  INFO 22044 --- [nio-8080-exec-2] c.e.a.trace.logtrace.FieldLogTrace       : [c0f5fc0a] |   |   |<--OrderController.request() time=1006ms
   | 
 
Thread 를 이용한 테스트 코드 작성
@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){             e.printStackTrace();         }     } }
   | 
 
@Slf4j public class FieldServiceTest {
      private FieldService fieldService = new FieldService();
 
      @Test     public void field(){         log.info("main start");         Runnable userA = () -> {             fieldService.logic("userA");         };
          Runnable userB = () -> {             fieldService.logic("userA");         };
          Thread threadA = new Thread(userA);         threadA.setName("thread - A");         Thread threadB = new Thread(userB);         threadB.setName("thread - B");
          threadA.start();         sleep(2000);         threadB.start();     }
      private void sleep(int millis){         try {             Thread.sleep(millis);         }catch (Exception e){             e.printStackTrace();         }     } }
   | 
 
14:10:58.072 [Test worker] INFO com.example.advancedspring.trace.threadlocal.FieldServiceTest - main start 14:10:58.076 [thread - A] INFO com.example.advancedspring.trace.threadlocal.code.FieldService - 저장 name=userA -> nameStore = null 14:10:59.081 [thread - A] INFO com.example.advancedspring.trace.threadlocal.code.FieldService - 조회 nameStore = userA 14:11:00.078 [thread - B] INFO com.example.advancedspring.trace.threadlocal.code.FieldService - 저장 name=userB -> nameStore = userA 14:11:01.080 [thread - B] INFO com.example.advancedspring.trace.threadlocal.code.FieldService - 조회 nameStore = userB
   | 
 
동시성 이슈가 발생하는 코드
@Test public 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(100);     threadB.start();
      sleep(2000);  }
   | 
 
14:32:12.377 [Test worker] INFO com.example.advancedspring.trace.threadlocal.FieldServiceTest - main start 14:32:12.381 [thread - A] INFO com.example.advancedspring.trace.threadlocal.code.FieldService - 저장 name=userA -> nameStore = null 14:32:12.483 [thread - B] INFO com.example.advancedspring.trace.threadlocal.code.FieldService - 저장 name=userB -> nameStore = userA 14:32:13.387 [thread - A] INFO com.example.advancedspring.trace.threadlocal.code.FieldService - 조회 nameStore = userB 14:32:13.489 [thread - B] INFO com.example.advancedspring.trace.threadlocal.code.FieldService - 조회 nameStore = userB
   | 
 
동시성 문제는 지역 변수에서는 발생하지 않는다. 지역 변수는 쓰레드마다 각각 다른 메모리 영역에 할당된다.
동시성 문제가 발생하는 곳은 같은 인스턴스의 필드 (주로 싱글톤에서 발생) 또는 static 같은 공용 필드에서 발생한다.