Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- programmers
- docker
- 코드워
- redis
- golang
- 알고리즘
- 프로그래머스
- 문제풀이
- codewars
- dynamic programming
- 동적프로그래밍
- 튜토리얼
- Java
- Linux
- DP
- 자바
- HBase
- boj
- scala
- leetcode
- 파이썬
- Go언어
- go
- OOM
- 주키퍼
- 스칼라
- Python
- gradle
- 리눅스
- zookeeper
Archives
- Today
- Total
파이문
멀티쓰레드에서 싱글톤 클래스 사용 예제 본문
728x90
싱글톤 클래스 예제는 보통 아래 처럼 작성되곤 한다.
public static class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
이렇게 작성하면 단일 쓰레드에서는 문제가 없지만, 멀티 쓰레드(multithread) 에서는 instance 를 가져올 때 (동시 접근하여 instance 를 null 로 판단한 경우) 문제가 생길 수 있다.
가장 쉬운 방법은 getInstance 함수에 synchronized 키워드를 넣는 것이지만, synchronized 는 성능상의 문제가 있다. 그래서 나온 방법이 LazyHolders 이다.
아래의 예제는 synchronized 로 된 싱글톤 클래스와 LazyHolder 기법이 적용된 싱글톤 클래스를 멀티쓰레드로 각각 돌리는 것이다.
import java.util.concurrent.CountDownLatch;
public class Singleton {
public static class SyncTickets {
private static int ticket;
private static SyncTickets instance;
private SyncTickets() {
}
public synchronized static SyncTickets getInstance() {
// 멀티 쓰레드 환경에서 싱글톤 인스턴스를 하나만 만들기 위해 synchronized 키워드를 넣는다.
// 단 성능상 문제가 있다.
if (instance == null) {
System.out.println("Call Only Once");
instance = new SyncTickets();
}
return instance;
}
public synchronized int getTicket() {
return ticket++;
}
}
public static class LazyTickets {
private static int ticket;
private LazyTickets() {
}
// JVM에게 객체의 초기화를 떠님기는 방식으로, 멀티스레드 환경에서도 객체의 단일성을 보장할 수 있다.
// Class 를 로딩하고 초기화하는건 JVM 의 영역이고 Thread Safe 를 보장한다.
public static LazyTickets getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final LazyTickets INSTANCE = new LazyTickets();
}
public synchronized int getTicket() {
return ticket++;
}
}
public static void main(String[] args) throws InterruptedException {
// 표준 출력에서 synchronized 적용된 싱글톤 클래스를 먼저 보려고 임의로 넣음
CountDownLatch countDownLatch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
SyncTickets tickets = SyncTickets.getInstance();
System.out.println(tickets.hashCode());
System.out.println("Sync-> " + Thread.currentThread().getName() + ":" + tickets.getTicket());
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
LazyTickets tickets = LazyTickets.getInstance();
System.out.println(tickets.hashCode());
System.out.println("Lazy-> " + Thread.currentThread().getName() + ":" + tickets.getTicket());
}).start();
}
}
}
'Java' 카테고리의 다른 글
JDK 14 톺아보기 (0) | 2020.10.07 |
---|---|
Mockito 를 사용하는 예제 (0) | 2020.09.25 |
CountDownLatch vs CyclicBarrier (0) | 2020.09.24 |
멀티쓰레드 환경에서 캐시 구현하기 (0) | 2020.06.27 |
Comments