[CS/운영체제] 멀티스레드와 동시성 - 29부

황제연·2025년 7월 28일
0

CS학습

목록 보기
149/193
post-thumbnail

미리 synchronized를 사용한다면?

앞서 기존 컬렉션 프레임워크에는 synchronized가 적용되어있지 않기 때문에,
프록시 패턴을 사용해서 synchronized를 적용하는 예제를 만들어봤습니다

그런데 만약 이렇게 만들지 않고 자바에서 모든 자료구조에 synchronized를 미리 적용해둔다면 어떨까요?

성능 트레이트 오프

synchronized, Lock, CAS등 모든 방식은 결국 성능과 트레이드 오프가 있습니다
결국 동기화를 사용하지 않는 것이 가장 빠르다고 할 수 있습니다

컬렉션 프레임워크는 항상 멀티스레드에서 사용되는 것이 아닙니다
미리 동기화를 해둔다면 단일 스레드 환경에서 사용할 때도 동기화로 인해 성능이 저하됩니다
동기화가 필요한 경우만 동기화를 적용하는 것이 필요합니다

Vector

과거 자바에서 이러한 실수를 한 사례가 바로 java.util.Vector클래스입니다
ArrayList와 같은 기능을 제공하는데 메소드에 synchronized를 통한 동기화가 되어있습니다

이 클래스는 단일 스레드 환경에서도 불필요한 동기화로 인해 성능저하가 발생했고
결과적으로 거의 사용하지 않고 있습니다
지금은 하위호환을 위해 남겨져있고 다른 대안이 많기 때문에 사용을 권장하지 않습니다

그렇다면 방법은?

가장 좋은 대안은 앞서 만든 synchronized를 적용해주는 프록시를 만드는 방법이 있습니다
자바는 이러한 컬렉션을 위한 프록시 기능을 제공합니다

List<Integer> list = Collections.synchronizedList(new ArrayList<>());

관련 코드를 더 살펴보면 아래와 같습니다

public static <T> List<T> synchronizedList(List<T> list){
	return new SynchronizedRandomAccessList<>(list);
}

앞서 만든 예제와 비슷한 방식으로 프록시 패턴을 적용해서
synchronized 코드블록을 제공하고 이후 관련 기능을 실행하는 것을 확인할 수 있습니다

Collections가 제공하는 synchronized 동기화 메소드

Collection는 다음과 같은 다양한 synchronized동기화 메소드를 지원합니다

  • synchronizedList()
  • synchronizedCollection()
  • synchronizedSet()
  • synchronizedMap()
  • synchronizedNavigableMap()
  • synchronizedNavigableSet()
  • synchronizedSortedMap()
  • synchronizedSortedSet()

Collections가 제공하는 동기화 프록시 덕분에 스레드 세이프하지 않은 컬렉션을
편리하게 스레드 세이프한 컬렉션으로 변경해서 사용할 수 있습니다

Synchronized 프록시 방식의 단점

하지만 synchronized프록시를 사용하는 방식도 단점이 존재합니다

동기화 오버헤드

synchronized 키워드가 멀티스레드 환경에서 안전한 접근을 보장하지만,
각 메소드 호출시마다 동기화 비용이 추가됩니다
이것 때문에 성능저하가 발생할 수 있습니다

잠금 범위 확대

전체 컬렉션에 대한 동기화가 이루어지기 때문에, 잠금범위가 넓어질 수 있습니다
이것은 잠금 경합(Lock Contention)을 증가시키고, 병렬 처리의 효율적을 저하시키는 원인이 될 수 있습니다
또한 모든 메소드에 동기화를 적용하다보면 특정 스레드가 컬렉션을 사용하고 있을 때
다른 스레드들이 대기해야하는 상황이 빈번해질 수 있습니다

정교한 동기화 불가

synchronized 프록시를 사용하면 컬렉션 전체에 대한 동기화가 이루어지지만,
특정 부분이나 메소드에 대해 선택적으로 동기화를 적용하는 것은 어렵습니다
이것은 과도한 동기화로 이루어질 수 있습니다

정리

즉 프록시 패턴을 적용하는 방식은 모든 메소드에 synchronized를 걸어버리는 것입니다
따라서 동기화에 대한 최적화가 이루어지지 않습니다

자바는 이런 단점을 보완하기 위해 java.util.concurrent패키지를 통해
동시성 컬렉션(Concurrent Collection)을 제공합니다

참고

  • 김영한의 실전 자바 - 고급 1편
profile
Software Developer

0개의 댓글