싱글톤 패턴.
많이들 들어봤을 초반에 배우는 디자인 패턴중 하나다.
내가 다녔던 굽,비에서도
===
public class ExampleSingleton {
private static ExampleSingleton instance;
private ExampleSingleton() {}
public static ExampleSingleton getInstance() {
if (instance == null) {
instance = new ExampleSingleton();
}
return instance;
}
}
===
이런식으로 배웠었다.
스태틱 변수로 인스턴스를 만들고 생성자를 폐쇄해서 인스턴스에 다른 곳에서 직접 접근 불가능하게 만들어라.
진입점은 단일 진입점인 퍼블릭 스태틱 메서드를 통해 접근하여 인스턴스가 없으면 반환 시키게끔 한다.
하지만 이런 생각의 전환도 가능하다.
싱글톤은 Caller가 달라도 언제나 동등한 객체를 반환하면 되지 않을까?
위 기본적인 코드가 지니는 문제점은 무수히 많다.
한 번 생각 해보자.
1. 멀티스레딩 환경에서 프로세스의 힙을 공유하는 T1, T2...Tn이 동시에 접근하여 해당 인스턴스 접근시 경쟁한다면 반환받은 객체의 동등성을 보장할수 있는가?
2. 싱글턴 인스턴스에 상태를 두면 어떤 상황이 발생하는가?
3. 스프링 프레임워크에서 빈은 싱글톤으로 반환된다고 하는데 상단 코드와 비슷한 방식으로 반환하는가?
4. 그렇지 않다면 어떠한 방법으로 스프링 프레임워크는 싱글톤 패턴을 사용하여 스프링 빈 객체를 반환하는가.
위 4가지의 고민을 통해서 생각의 지평을 넓혀보자.
기본적인 부분도 은근히 생각할 지점이 많아진다.
화이팅이다 모두.
null인 상태에서 여러 쓰레드가 동시에 체크하면 서로 다른 address를 리턴받는 동시성 문제가 생기지 임계구역으로 만들어서 배타적 영역으로 만들면 되고 구현은 알아서.. 싱글톤 객체는 로컬인스턴스 단위로 잡히니깐 멀티인스턴스에서 공유되지 않는 문제가 있고 기본적으로 메모리에 유지되니 재시작시 초기화되는 문제가 있지 싱글톤에 그래서 값을 저장하는건 신중하여야함 - dc App
역시 대단.. 취준들은 가시성, volatile variable, atomic class, CAS 같은 키워드로 학습하면 좋을 듯. - dc App
@99.9(58.237) Spring에서 Controller Service 레파지토리도 마찬가지로 싱글톤 객체로 생성되고 Addeess가 하나로만 잡힘 new Service() new Controller() 싱글톤 주소는 하나이고 내부에 Address를 저장하지 변수를 저장하면 안됨. 싱글톤은 한개이나, 여러쓰레드가 각자의 로컬 스택을 갖고 있어서 request요청마다 각각 다르게 값이 잡히도록 되는 방식 - dc App
@99.9(58.237) 공부한지 오래되서 정확한 자바 클래스명은 가물가물하네 - dc App
@99.9(58.237) Request 요청마다 각각 파라미터로 들어오는 값이 다르니 new Service()가 매번 생기는거 아니야? 라고 오해하기 쉬움 - dc App
@딘퐁 러프한 방향성은 오래됐어도 충분히 남아있어 보이네. IoC로 넘겨서 사용자가 new 안쓰고 주입 받는 부분에서 DI일어날 때 코어 내부에서 getSingleton() 메서드 호출해서 꺼내오는데 그 부분은 내일이나 주말에 날잡고 한번 써봐야겠음. 굿굿 - dc App
댓글 개웃기네 시발ㅋㅋ db얘기만 해야겠다
혹시 어떤부분이 틀림? - dc App
동시성얘기는 그냥 순수 자바 기준으로 말한거거 프레임워크에서는 동시성제어 신경안써도되는건 나도 알음.. - dc App
@딘퐁 니가 말한건 싱글톤의 특성이 아니고 서버 인메모리 특성이잖아
@ㅇㅇ(103.246) 그부분이 핀트가 이상하긴하네 메모리특성이지 동시성 얘기가 나와서 싱글톤 안에 어떤 count 값을 동시에 접근하는 예시를 생각하다보니 확장해보래서 거기까지 말했어.. - dc App
@ㅇㅇ(103.246) 2번에서 싱글톤안에 int counter =0; counter++; 생각하다가 다른대로 샌거같아 싱글톤도 메모리의 일부지만 그게 싱글톤이 가진 문제라는건 아니였어 ㅠ - dc App
@딘퐁 싱글톤에 int counter 같은 값을 저장하면 안되는 이유 - dc App
내가 알기로는 GoF에서 말하는 싱글톤이랑 스프링 프레임워크가 관리하는 싱글톤이랑은 다른 걸로 앎.. IoC 컨테이너 안에서 컨테이너가 생명주기 관리하고 하는게 차이점이 아닌가 싶음.. 그게 3 4번 질문에 답이 되는건지.. 어렵노..
본질적으로 같다 스프링이라는 ioc 프레임워크를 쓰기때문에 싱글톤동시성같은 좆빠는 소리를 생각안해도됨
GoF에서 말한걸 스프링 프레임워크는 어떤식으로 구현했을까?에 대한 부분이라, 위에서 적은것처럼 Caller가 어디던 상관없이 동등한 target을 반환하면 싱글턴이 아닐까?로 접근해보면 좋을것 같아. - dc App
힌트는 유일 객체 등록, 동등 객체 반환에 필요한 자료구조 생각해보면 더 좋아 - dc App
@99.9 그럼 유일 객체를 등록하고 동등 객체를 반환해야 하니까 key-value 식으로 하는건가 싶노.. bean 이름으로 구분했나 뭐 그런걸 key에 넣고 value는 bean 인스턴스 이런식.. 근데 빈 간에 순환참조? 경쟁상태면 이거만으로 안되니까 뭔가 더 복잡한게 이면에 있지 않을까 싶음.. 모르는게 너무 많다 싶다..
@ㅇㅇ 좋은 접근이야 키벨류인데 키벨류중 키의 유일성, 벨류의 유일성은 다르니까 그부분을 좀 더 깊게 생각해봐. 접근방법 좋아 - dc App
@ㅇㅇ 순환참조가 필요한 경우엔 eager생성 - 캐싱 - 탐색 - 캐시 히트시 반환 - 이후 eager - 최종객체 매핑 이런게 있는데 그건 따로 글써볼게 - dc App
싱글톤은 Caller가 달라도 언제나 동등한 객체를 반환하면 되지 않을까? -> 이 말부터 문제가 있는 거 같아. Caller 관점에서 동등하다고 볼 수 있는 거는 참조랑 값이 있는데, 전자는 보장하지만 후자는 보장하지 못해. 그래서 1번만으로는 불가능한거고, 그래서 결과가 보장되려면 추가 작업이 필요. 스프링 같은 경우에는 저렇게 안한다는 거는 알겠는데, 흠...모르겠네. (아마 컨테이너마다 관리하는 거 아님?) - dc App
스프링은 모든 싱글톤 빈을 하나씩 만들어놓은 뒤에 의존성 주입이 시작되고 의존성 주입이 끝나면 다시는 생성을 할 일이 없기때문에.. 동시성 문제가 안생김
전자와 후자를 보장한다를 레이어를 나누듯 나눠봐. 빈을 등록할때 non duplicate key, 가져올때 identity 동등성. 빈이라는걸 하나두고 등록할때 / 가져올때 를 구분지어 상각해보면 생각이 열릴거야 - dc App
@99.9 답변해줘서 고마워, 본문만 읽고 생각한대로 댓글 적은거라, 답변으로 말해준 내용으로 생각해봤어. 그 이후에 생성을 할 일이 없다는 거, 레이어 나누듯이 생각하라는 거는... 등록하는 거랑 가져오는 거랑은 별개로 생각하라는 거로 이해했고. 빈을 등록할 때 non duplicate key : 해당되는 키로 등록되는 거는 하나만 (중복 등록 방지) 빈을 조회할 때 identity 동등성 : 같은 키면 참조가 같은 값을 반환-> 같은 컨테이너에서 반환하는 값은 동일한 참조 값을 반환 요약하면 스프링 빈 생성 시에 유일성 보장, 조회 시에 반환된 참조값에 대한 동일성 보장으로 일단 생각을 정리했어 - dc App
@폭주린 맞아, 거기서부터 시작해서 해당 요구사항을 만족하는 자료구조나, 구현 방법을 떠올리게되면 끝인거야 - dc App
1, 2 -> 이기 때문에 싱글톤은 전역적인 상태 초기화같은 작업을 빼면 동적인 연산을 해서는 안됨. 만약 어떤 상태를 저장한다면 T1이 얻은 객체의 상태랑 T2가 얻은 객체의 상태가 다를 수 있기 때문임. 좋은 예: 오디오 매니저에서는 첫 초기화 때 로드된 오디오만 틀어주도록 한다
굿굿 공유가 필요한 상황에서는 원자적 연산과, 가시성을 보장하자 ! - dc App
Java는 그낭 inner class에 ststic 멤버 쓰면 jvm이 lazy loading 이랑 thread safe랑 다 챙겨준대
자 바 사 랑 해 - dc App
Spring에서 싱글톤 어떻게 만드는지까지 알아야하나 싶긴 한데 코드 까보면 그냥 락 걸었네
https://github.com/spring-projects/spring-framework/blob/824aa137f8ec1218049f3017fa23072db503467d/spring-beans/src/main/java/org/springframework/bea
원래 synchronized 였다가 가상스레드 이슈로 락으로 바뀐거일거고...ㅡ
상태를 가지고 있으면 전역변수처럼 쓸 수 있는데 읽기/쓰기에 thread safe가 필요한지 잘 봐야겟지...
스프링을 모르는듯.