Entity
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class MyEntity {
@Id
@GeneratedValue
private Long id;
private int number;
public void addNumber() {
this.number++;
}
public int getNumber() {
return this.number;
}
}
Service.class
@Service
@RequiredArgsConstructor
public class ConcurrentService {
private final MyRepo myRepo;
@Transactional
public void concurrentlyEdit() {
MyEntity myEntity = myRepo.findAll().get(0);
myEntity.addNumber();
}
}
Test
@Test
void test() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(5);
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
executorService.execute(()->{
service.concurrentlyEdit();
latch.countDown();
});
}
Thread.sleep(10000);
System.out.println(myRepo.findAll().get(0).getNumber() + " hello");
}
하고자하는것은
CountDownLatch latch = new CountDownLatch(5);은 5개의 스레드가 종료될때까지 기다릴거다
그리고 5개의 스레드를 실행시켜 동시에 myEntity의 number를 증가시킨뒤 올바르게 반영되는지 확인
만약 내가 이해한대로 트랜잭션 레벨2가 한 트랜잭션에서 데이터에 접근하는동안 다른 트랜잭션에서 해당 데이터를 수정할 수 없다면
절대 결과는 5가 나올 수 없다.
그럼 레벨2면 동시성 문제에 대한 걱정없이 막 쓰면되는거아냐?
격리수준 레벨2는 결국 락을 사용한다.
트랜잭션 격리수준 레벨2의 특징이 무엇인가? 레벨이 높아질수록 결국 동시성을 포기하고 무결성을 선택한다.
비관적락 사용시 문제점이 무엇이었는가?
- 트랜잭션 충돌을 예상해서 미리 락걸고 수행한다
- 그럼 결국 많은 요청이 들어오면 그 요청을 수행할때마다 락걸고 동작하고 이는 당연히 성능상 문제가 발생할 수 있다.
솔직히 말하자면 아직까진 락없이 성능을 유지하면서 동시성문제를 제어할 수 있는 방법이 무엇인지 모르겠다.
다만 지금처럼 알고있는 지식을 확인함으로써 다음에 이해해야할 내용을 보다 쉽게 이해할 수 있지 않을까한다
개요:
하고자하는것은
그럼 레벨2면 동시성 문제에 대한 걱정없이 막 쓰면되는거아냐?