SELF STUDY/Design Pattern

[디자인 패턴] 싱글톤 패턴

호이호이호잇 2021. 7. 14. 00:47
728x90
반응형

 

디자인 패턴 공부.. 

숙제가 블로그에 정리하기였는데.. 이제야 정리하네요ㅕ,, 하하

 

다음엔 일등으로 해보겠습니다..!

 

싱글톤 패턴이란?

싱글턴 패턴은 인스턴스가 딱 1개만 생성되야 하는 경우에 사용되는 패턴

 

프린터로 예를 들면, 아래 사진처럼 "프린터" 한 대가 있고, 이 프린터를 8명의 user가 사용하길 원하고 있는 상황이 주어져 있다. 프린터 사용에 대한 과정을 코드로 작성해본다면 어떻게 하면 될까?

제안 1.

단순하게 생각하면, Printer를 관리하는 소스는

이렇게 구현하면 될 것 같다.

 

하지만 위의 소스처럼 구현을 하게되면, "public"으로 되어 있기 때문에 접근하는 사용자마다 PrinterManager 객체를 생성하게 되고 그럼 총 8개의 PrinterManager 객체가 생성되어 하나의 Printer를 관리하는 것이 아니게 된다. 

즉 아래의 그림과 같이 총 8개의 PrinterManager가 생성된다.

 

궁극적으로 하고 싶은 구현 방법은 아래 그림과 같이 한 대의 프린터를 8명의 유저를 줄세워 차례대로 사용하게 하는 것이다.

 

제안 2.

그러면 생성되는 객체가 한 번만 생성되도록 객체 자체를 "private static" 변수로 만들면 될까?

이렇게 구현 했을 때, 되는 것 같다고 생각이 들었고 main에 구현을 해보았을때 되는 것 처럼 보였다.

 

실제 사용에 맞춰 thread를 이용해 구현 및 테스트를 해보았다.

 

- Printer.java

Printer 객체를 나타냄.

sleep 은 최대한 실제 사용자의 사용과 같게 나타내기 위해 추가해 준 것.

 

- UserThread.java

사용자가 printer 에 접근함을 나타냄.

 

- Test.java

 

테스트 소스를 실행한 결과는 다음과 같다.

결과에서 @뒤에 나온 숫자가 printer 객체를 나타내는데, 다 다른 것을 볼 수가 있다.

 

결국 다시 

이런 형태의 구현이 된 것이다.

 

원인은 "경합조건"이다.

경합 조건(Race condition) 이란? 

메모리와 같은 동일 자원을 2개 이상의 쓰레드가 사용하려 하는 것 이다.

 

 

제안 3.

위의 문제를 수정하기 위해서는 "동기화" 가 필요하다.

동기화란?

하나의 스레드만 접근이 허용하도록 하는 것 이다.

동기화에는 함수 / 변수 동기화가 있다.

  - 함수 동기화 : synchronized void method()

  - 변수 동기화 : synchronized(obj)

이런식으로 사용된다.

 

- Printer.java

printer 접근 수를 세어주는 counter 변수도 추가해주었다.

 

- 결과

printer id는 1개가 생성되어 동기화가 된 것을 확인 할 수 있다.

counter에 대한 경합 조건이 충족되어 중복되는 수가 나오는 것을 볼 수 있다.

 

counter 처리는 어떻게 해주는 것이 좋을까?

counter 변수를 사용하는 곳에도 "동기화"를 해주면 된다.

 

 

제안 4.

counter 변수를 다루는 print 함수에도 동기화를 추가해보았다.

- Printer.java

 

- 결과

counter가 동기화되어 순서대로 나오는 것을 볼 수 있다.!

 

 

이상으로 싱글톤에 대해 알아보았다.

 

실제 안드로이드에서 사용되는 것을 보고 싶어서 찾아보았는데,

블루투스, 프린터, nfc 등등에서 사용되는 것 같았다.

 

한눈에 보기 쉬운 것은 블루투스 소스 같아서 가져왔다.!

참고해서 보면 좋을 듯 하다.

 

- frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java

디자인 패턴 어렵다..

세상에 쉬운 공부는 없구나 ㅠ

이해 아직 완벽히 되진 않은 것 같다..

다음엔 동기화 synchronized 좀 공부해봐야겠다..!

 

끄읐

728x90
반응형