본문 바로가기

STUDY

[패턴(Thread)]Immutable Pattern

Immutable Pattern

1. 의미

저 단어의 의미는 변하지 않는다라는 의미를 가지고 있다.

반대로 Mutable이라는 단어는 변한다라는 의미를 지니고 있다. 여기서 가장 쉽게 유추할 수 있는 내용은 무언가 변하지 않는구나 라는 것을 짐작 해볼 수 있다.

 

String str1 = "A";

String str2 = new String("B");

String str3 = "A";

 

str1에는 A라는 문자열이 메모리상에 위치한 주소값만 가지고 있다. 참조값을 가지고 있는 것이다. str2에서는 new 키워드를 사용해 String을 새롭게 생성한다. B라는 문자열이 메모리상에 생성되어 str2라는 변수가 주소값을 참조하게 되어 있다.

그렇다면 str3은 어떨까 ?

str1과 같이 같은 문자를 대입하고 있다. str1과 str3은 달라질까 ? 아니다. 메모리상에 생성하기 이전에 풀에서 같은 문자열이 존재하는지 찾게 된다. 이때 A라는 문자가 이미 생성되어 있기 때문에 str3은 그저 A라는 문자가 존재하는 주소만 참조하게 된다.

String 클래스는 ReadOnly이다. 내부적으로 String 클래스는 쓰기를 제공하지 않는다,

예를 들어

StringBuffer sb = new StringBuffer();

sb.append("1234");

처럼 StringBuffer을 생성한다하더라도 StringBuffer 자체에서 문자열을 변경하거나 하는 작업을 하지는 않는다.

말하자면,

String는 Immutable한 클래스이고

StringBuffer는 Mutable한 클래스이다.

 

2.Immutable pattern은 ?

위에서 다 얘기했듯이 이 패턴은 변하지 않는 읽기만 제공하는 클래스 String 클래스 같은 것을 얘기한다. 그러나 우리가 이 패턴을 적용하고 만들기 위해서는 어떤 조건을 만족해야 하는걸까 ?

첫번재로, 설계단계에서의 클래스 설계에서부터 Immutable한 클래스와 Mutable한 클래스가 나뉘어져야 한다고 본다. 인스턴스의 상태가 변해야만하고 변하지 말아야하는 것은 동시에 공존할 수 없기 때문에 Immutable한 클래스에서 Mutable한 클래스를 생성하는 것과, Mutable한 클래스에서 Immutable한 클래스를 만드는 것 둘중에 한가지 방법을 바탕으로 한 클래스 설계가 미리 이루어 져야 할 것이다.

두번째로, 외부에서 인스턴스를 변화시킬만한 요인을 제거한다. 이 내용은 Immutable 패턴을 적용하는 가장 중요한 핵심이다. 내용은 아래와 같다.

1.클래스에서 Setter를 제공하지 않는다. No Setter

2.Private과 final을 활용하여 클래스 생성시점에서 변수를 초기화하고 외부에서 직접적인 변수의 접근을 사전에 차단하도록 한다.

 

3. 이점 ?

변하지 않는거라면 안전성을 보장받기 위한 것 아닌가 ? 그럼 synchronized를 사용하면 보장받을 수 있지 않은가라고 말할 수도 있다. 이러한 질의는 성능적인 측면과 Immutable한 클래스와 synchronized 키워드가 사용된 클래스의 차이점에서 해석해보겠다.

1. 성능

예제를 돌려봐도 알겠지만 10억번을 돌려서 나오는 결과는 3초 정도 차이가 났다. Immutable 클래스의 속도가 더 빠른 것임을 증명한다. Synchronized된 클래스는 복수의 Thread가 접근할때 우선권을 얻고 해제하는 일련의 과정이 필요하며, 복수의 Thread 중 동시에 하나만이 접근할 수 있기 때문에 당연히 운용시간에 있어서 차이가 난다.

2. 안전성

Synchronized 키워들 사용한다고 해서 완전하게 안전할 수 있을까 ? 그럴 수도 있다라는 추측일 뿐이고 결과가 그렇다고 하여 변화하는 인스턴스를 복수의 thread로부터 보호한다고해서 끝까지 안전하리라고는 보장 할 수 없다.

그러나 Immutable한 클래스는 쉽게 초기화된 클래스를 ReadOnly하는 것 뿐이기 때문에 안전하다 할 수 있다.

3. 지속성

Synchronized한 클래스는 복수의 Thread가 하나의 인스턴스를 공략하다보면 락을 취득하고 해제하는 일련의 과정에서 데드락이 걸려버릴수도 있다. 예를 들어 스테이크를 먹는데 포크랑 칼이랑 필요한데 두명이 동시에 한명은 포크 한명은 칼을 드는 경우일 수도 있다. 이럴때는 지속성을 보장받지 못한다.

 

Synchronized 키워드를 사용하지 않는다. 라는 이유만으로 저러한 위험성에서 벗어날 수 있는 것이다. 하지만 필히 synchronized를 매우 잘 사용해야 하는 경우가 immutable한 클래스를 만드는 경우보다 더 많을 것이라 생각되어서 synchronized 동기화라는 것에 대해 항상 고민하는 것 같다.

패턴은 참 재밌다.