String은 불변
- String은 불변기본적으로 자바에서는 String 객체의 값은 변경할 수 없다.
- 이는 한번 할당된 공간이 변하지 않는다고 해서 '불변(immutable)' 자료형 이라고 불리운다. 그래서 초기공간과 다른 값에 대한 연산에서 많은 시간과 자원을 사용하게 된다는 특징이 있다.
- 실제로 String 객체의 내부 구성 요소를 보면 인스턴스 생성 시 생성자의 매개변수로 입력받는 문자열은 이 value 라는 인스턴스 변수에 문자형 배열로 저장되게 된다. 이 value 라는 변수는 상수(final)형이니 값을 바꾸지 못하는 것이다.
public final class String implements java.io.Serializable, Comparable {
private final byte[] value;
}
StringBuffer/StringBuilder는 가변
- StringBuffer나 StringBuilder의 경우 문자열 데이터를 다룬다는 점에서 String 객체와 같지만, 객체의 공간이 부족해지는 경우 버퍼의 크기를 유연하게 늘려주어 가변(mutable)적이라는 차이점이 있다.
- 두 클래스는 내부 Buffer(데이터를 임시로 저장하는 메모리)에 문자열을 저장해두고 그 안에서 추가, 수정, 삭제 작업을 할 수 있도록 설계되어 있다.
- StringBuilder(가변) 비동기방식이기 때문에 Single Thread 환경하에서, 변화되는 문자열의 사용한다. 비동기방식이기 때문에 처리속도는 제일 빠르다.
- StringBuffer(가변) 동기방식으로 저장되기 때문에 멀티쓰레드로 접근하거나 문자열이 변경될 경우에 사용한다.
- 이 질문의 의도는 동기, 비동기의 기준으로 보인다.
2-1. thread safe
- thread safe란 멀티 스레드 프로그래밍에서 일반적으로 어떤 함수나 변수, 혹은 객체가 여러 스레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없음을 뜻한다.
- 보다 엄밀하게는 하나의 함수가 한 스레드로부터 호출되어 실행 중일 때, 다른 스레드가 그 함수를 호출하여 동시에 함께 실행되더라도 각 스레드에서의 함수의 수행 결과가 올바로 나오는 것으로 정의한다.
Thread-safe를 지키기 위한 방법
- Re-entrancy(재진입성)
어떤 함수가 한 스레드에 의해 호출되어 실행 중일 때, 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 올바로 주어져야 한다.
- Thread-local storage(TLS)
공유 자원의 사용을 최대한 줄여 각각의 스레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는다.
이 방식은 동기화 방법과 관련되어 있고, 또한 공유상태를 피할 수 없을 때 사용하는 방식이다.
- Mutual exclusion(상호배제)
공유 자원을 꼭 사용해야 할 경우 해당 자원의 접근을 세마포어 등의 락으로 통제한다.
- enterCS() primitive (primitive: 기본 연산)
- Critical section 진입 전 다른 프로세스가 critical section 안에 있는지 검사를 합니다.
- Critical section에 다른 프로세스가 있다면 비어 있을 때까지 대기를 합니다.
- exitCS() primitive
- Critical section을 벗어날 때의 후처리 과정을 합니다.
- Critical section을 벗어남을 표시하게 됩니다.
- Atomic operations
공유 자원에 접근할 때 원자 연산을 이용하거나 '원자적'으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현할 수 있다.
<aside>
💡 원자적 연산이란?
중단되지 않는 연산
여러 쓰레드가 공용 자원을 동시에 접근하는 것을 데이터 레이스라고 한다. 이를 막기 위해 먼저 실행된 쓰레드가 커밋이 된 후 다음 쓰레드가 데이터를 읽고 변경할 수 있다.
</aside>