불변성과 성능 위주로 공부하기! String vs StringBuffer vs StringBuilde

Java에서 문자열을 다룰때 사용하는 String, StringBuffer, StringBuilder 클래스는 각각의 특성과 사용 목적이 다르다

String

  • 불변(Immutable) 객체
  • 한 번 생성되면 값 변경 불가
  • 문자열을 조작 시 새로운 String 객체가 생성되어 메모리를 추가로 사용
  • 문자열 연산이 많을 경우 성능이 저하될 수 있다
  • 불변성 덕분에 스레드에 안전(Thread-safe)
  • 스레드 세이프하기때문에 String 객체를 여러 곳에서 자유롭게 공유 가능

StringBuffer

  • 가변(Mutable) 객체
  • 문자열 조작 시 기존 객체의 값을 변경
  • 멀티스레드 환경에서 동기화(synchronized)를 지원하므로 스레드 세이프 가능
  • 하지만 동기화로 인해 오버헤드가 발생할 수 있어 단일 스레드 환경에서는 성능이 떨어질 수 있다

StringBuilder

  • 가변(Mutable) 객체
  • 문자열 조작 시 기존 객체의 값을 변경
  • 동기화를 지원하지 않아, 스레드 세이프하지는 않으나 성능은 가장 뛰어남
  • 동기화에따흔 오버헤드가 존재하지 않아 단일 스레드 환경에서 가장 적합

요약

  • 문자열을 많이 다루는 상황에서는 StringBuilder
  • 멀티스레드 환경이라면 StringBuffer
  • 문자열 변경이 필요 없고 공유가 많다면 String

    클래스 불변성 동기화 스레드 세이프 성능 (단일 스레드)
    String O - O 낮음
    StringBuffer X O O 중간
    StringBuilder X X X 높음

추가 정리

Thread Safe

멀티스레드 환경에서 여러 스레드가 동시에 같은 코드나 데이터에 접근해도 프로그램의 실행 결과가 안정적으로 유지되는것

구현 방법

1. 동기화(Synchronization)

  • 여러 스레드가 공유 자원에 동시에 접근하는 것을 제한
  • 한 번에 하나의 스레드만 해당 리소스를 사용할 수 있도록 함
  • Java에서는 synchronized 키워드로 구현 가능

2. 뮤텍스(Mutex) / 세마포어(Semaphore)

  • 운영체제 수준에서 제공하는 동기화 방법
  • 공유 자원에 대한 동시 접근을 제어

3. 원자적 연산(Atomic Operation)

  • CPU 차원에서 더 작은 단위로 쪼개지지 않고 한 번에 수행되는 연산
  • 예: Java의 AtomicInteger

4. Lock-free / Wait-free 구조

  • 락(lock) 없이도 스레드 간 충돌 없이 정상 동작을 보장하는 알고리즘 사용


OverHead

  • 작업을 수행할 때 필수 작업 외에 추가적으로 드는 자원이나 시간을 의미
  • 일반적으로 성능저하의 원인

동기화에서 발생하는 대표적인 오버헤드

1. 대기 시간

  • 동기화된 블록 또는 메서드에 한 번에 하나의 스레드만 접근 가능
  • 때문에 나머지 스레드들은 대기 상태에 놓여 실행이 지연

2. 컨텍스트 스위칭(Context Switching)

  • CPU가 현재 실행 중인 스레드나 프로세스의 상태를 저장하고, 대기 중인 다른 스레드나 프로세스로 전환하는 과정
  • 스레드가 공유 리소스에 접근할 때마다 컨텍스트 스위칭이 발생한다
  • 이때 발생하는 자원 소비와 시간 낭비가 오버헤드로 작용한다

댓글남기기