이전 글에서 진행했던 Syncronized 키워드의 경우 실무에서 적용하기 어렵습니다. 그 이유로는,
1. @Transactional과 Syncronized를 같이 사용할 경우, 동시성을 보장해주지 못합니다.
Spring AOP를 적용할때 프록시 객체를 생성하게 됩니다.
public void proxy() {
EntityTransaction tx = em.getTransaction();
tx.begin();
super.service();
tx.commit();
}
이런 형태로 Syncronized가 걸린 메서드의 겉을 덮는 프록시가 생성 되기 때문에, Syncronized가 걸린 service() 로직을 실행한후 트랜잭션이 커밋 되기 직전에 다른 스레드에서 service를 호출할 수 있습니다. 그 결과, 동시성을 보장하지 못하게됩니다.
해결방법으로는 자바에서 제공하는 Lock을 사용하여 해결할 수 있습니다.
ex.) 간단한 로직
private final Lock lock = new ReentrantLock();
public void sync() {
lock.lock();
try {
//logic
} finally{
lock.unlock();
}
}
ex.) 락이 여러개일때,
private ConcurrentHashMap<String, Lock> locks = new ConcurrentHashMap<>();
public void sync(Long userId) {
Lock lock = locks.computeIfAbsent(String.valueOf(id), key -> new ReentrantLock());
boolean acquiredLock = lock.tryLock(3, TimeUnit.SECONDS);
if (!acquiredLock) {
throw new RuntimeException("Lock 획득 실패");
}
try {
//logic
} finally {
lock.unlock();
}
}
2. 실무에서는 서비스의 안정성과 확장성을 고려하여 대부분 다중 서버를 이용합니다. 하지만, 다중 서버의 경우 Syncronized 키워드는 서버 각각에만 적용됨으로 동시성을 보장해주지 못합니다.
해결방법으로는 데이터베이스 락, 분산락이 있습니다.
1. 데이터베이스 락 ( JPA 락)
2. 레디스 분산락
'Back-end' 카테고리의 다른 글
TDD와 DDD (0) | 2024.07.29 |
---|---|
Spring DI에 동작원리 (0) | 2024.02.05 |
이전 글에서 진행했던 Syncronized 키워드의 경우 실무에서 적용하기 어렵습니다. 그 이유로는,
1. @Transactional과 Syncronized를 같이 사용할 경우, 동시성을 보장해주지 못합니다.
Spring AOP를 적용할때 프록시 객체를 생성하게 됩니다.
public void proxy() {
EntityTransaction tx = em.getTransaction();
tx.begin();
super.service();
tx.commit();
}
이런 형태로 Syncronized가 걸린 메서드의 겉을 덮는 프록시가 생성 되기 때문에, Syncronized가 걸린 service() 로직을 실행한후 트랜잭션이 커밋 되기 직전에 다른 스레드에서 service를 호출할 수 있습니다. 그 결과, 동시성을 보장하지 못하게됩니다.
해결방법으로는 자바에서 제공하는 Lock을 사용하여 해결할 수 있습니다.
ex.) 간단한 로직
private final Lock lock = new ReentrantLock();
public void sync() {
lock.lock();
try {
//logic
} finally{
lock.unlock();
}
}
ex.) 락이 여러개일때,
private ConcurrentHashMap<String, Lock> locks = new ConcurrentHashMap<>();
public void sync(Long userId) {
Lock lock = locks.computeIfAbsent(String.valueOf(id), key -> new ReentrantLock());
boolean acquiredLock = lock.tryLock(3, TimeUnit.SECONDS);
if (!acquiredLock) {
throw new RuntimeException("Lock 획득 실패");
}
try {
//logic
} finally {
lock.unlock();
}
}
2. 실무에서는 서비스의 안정성과 확장성을 고려하여 대부분 다중 서버를 이용합니다. 하지만, 다중 서버의 경우 Syncronized 키워드는 서버 각각에만 적용됨으로 동시성을 보장해주지 못합니다.
해결방법으로는 데이터베이스 락, 분산락이 있습니다.
1. 데이터베이스 락 ( JPA 락)
2. 레디스 분산락
'Back-end' 카테고리의 다른 글
TDD와 DDD (0) | 2024.07.29 |
---|---|
Spring DI에 동작원리 (0) | 2024.02.05 |