Programing/JAVA

static 메소드, 변수의 Thread safe, unsafe

리커니 2023. 6. 26. 13:24
반응형

1. static

자주, 반복적으로 사용하는 메소드를 개발할 때 고민해봐야 하는 것이 static의 사용입니다.

static 의 경우 new 키워드로 생성하여 Heap 에 저장되는 일반 객체와 달리,

GC의 대상이 되지 않는 Data 영역에 저장됩니다. 

이는 어플리케이션이 종료될 때 까지 메모리에서 해제되지 않음을 의미 합니다.

static 은 잘 사용하면 매우 유용하지만, 잘못 사용하거나 남발하게 되면 어플리케이션의 퍼포먼스에

악영양을 미치기 때문에 적절하게 사용해야 합니다.

 

link : https://aljjabaegi.tistory.com/636

 

Java GC Gargabe Collection 알짜만 빼먹기 / 알고리즘 / 종류 / 모니터링 VisualVM

Java GC Garbage Collection 알짜만 빼먹기 / 알고리즘 / 종류 / 모니터링 VisualVM 이번 포스팅에서는 제가 알고있는 Garbage Collection에 대해 정리하는 시간을 갖어볼까 합니다. GC (Garbage Collection) 란? GC는 JVM

aljjabaegi.tistory.com

 

2. Thread safe

static은 위에서 말씀드린 것과 같이 한번 메모리에 올라가게 되면 어플리케이션이 종료 될 때 까지 

메모리에서 해제되지 않습니다. 다르게 말하면, 접근하는 모든 Thread가 공유한다는 말이 됩니다.

특히, Multi Thread 환경에서 같은 static 변수나 메소드에 동시에 접근하게 되면 원하지 않은 결과를

얻을 수 있습니다. '이를 Thread safe 하지 않다 (unsafe하다)' 라고 표현합니다.

그럼 Thread safe 하게 구현하려면 어떻게 해야 할까요?

 

3. synchronized

가장 간단한 방법은 Thread safe 하길 원하는 변수나 메소드에 synchronized 키워드를 붙이는 것 입니다.

public class ThreadSafeTest {
    public static synchronized int testNum = 10;
    
    public static synchronized int getTestPlusNum(int plusNum) {
    	testNum += plusNum;
    	return testNum;
    }
}

이렇게 syncronized 키워드를 붙이게 되면 하나의 Thread에서 변수나 메소드에 접근하게 되면 해당 변수, 메소드가 Lock이 걸려 하나의 Thread에서만 접근이 가능하게 됩니다. 그리고 위의 코드는 아래의 코드와 동일합니다.

public class ThreadSafeTest {
    public static synchronized int testNum = 10;
    
    public static int getTestPlusNum(int plusNum) {
    	syncronized(ThreadSafeTest.class){
            testNum += plusNum;
            return testNum;
        }
    }
}

syncronized 키워드의 사용은 가장 간단한 방법이긴 하지만, 위에서 말씀드린데로, 메소드에 하나의 Thread가 접근하는 경우 Lock이 걸리기 때문에 시간이 오래 걸리는 메소드의 경우 상당한 퍼포먼스의 하락을 가져올 수 있습니다.

 

이는 singleton 패턴으로 생성된 객체나 spring bean을 활용할 때도 주의해야 될 것 입니다.

 

4.참고 Thread safe 하지 않은 SimpleDateFormat

Date 형 변환에 사용되는 SimpleDateFormat class 는 Thread safe 하지 않습니다.

그래서 static 으로 SimpleDateFormat 을 사용하는 경우 Multi Thread 환경에서는 주의 해야 합니다.

 

public static final SimpleDateForamt DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");

public static final testClzz() {
	.
    .
    .
    DATE_FORMAT.parse(strDate); // Thread safe 하지 않음!
    //new SimpleDateFormat("yyyyMMddHHmmss").parse(strDate); // Thread safe 함
    //DateTimeFormatter.ofPattern("yyyyMMddHHmmss", Locale.KOREA); // LocalDateTime을 return
}

그래서 SimpleDateForamt 사용 시 아래와 같이 새로운 Instance를 생성하거나 DateTimeFormatter 와 같이 Thread safe한 클래스의 메소드를 활용해야 합니다.

SimpleDateFormat 보다는 Java8 이후에 나온 DateTimeFormatter를 사용하고, Date 보다는 LocalDate 혹은 LocalDateTime을 활용하도록 합시다.

반응형