리뷰가 일으킨 단례 모델에 대한 사고

코드 디버깅에서memcached의connection을 볼 때 항상 100개 안팎으로 유지되는 것을 발견했습니다. 물론 이것은 문제없을 것 같습니다. 왜냐하면memcached의 기본connection은 1024개이기 때문입니다.그러나 내가 생각하는 것은 왜 100개가 있는지 하는 것이다. 왜냐하면 나의memcachedclient의 생성은 단례 모델을 사용하기 때문이다. 나는memcachedClientFactory 클래스를 정의했다. 주요 코드는 다음과 같다.

MemcachedClientFactory{
private MemcachedConnectionBuilder memcachedConnectionBuilder;
private String servers;
private static MemcachedClient memcachedClient;

private MemcachedClientFactory(){
}

private MemcachedClientFactory(MemcachedConnectionBuilder memcachedConnectionBuilder, String servers){
 this. memcachedConnectionBuilder= memcachedConnectionBuilder;
 this.servers=servers;
 }

public static MemcachedClient createClient(){
if(memcachedClient==null){
this.memcahcedClien= new MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));
}
 return this.memcahcedClient;
}
}
}

최초의 문제로 돌아가면 왜 100여 개의 연결이 있습니까?
위의 이 묘사는 정말 하나의 연결만 생기는 것을 보장할 수 있습니까?분명히 안 돼, 왜?다중 스레드 병발!문제는 여기에 있다. 여러 개의 라인이 동시에createClient () 방법에 들어갔을 때,memcachedClient가null로 판단되었을 때 여러 개의 연결이 생겼다.하, 문제를 찾았다.
향상된 기능:

public static synchronizd MemcachedClient createClient(){
 if(memcachedClient==null){
this.memcahcedClien=  new
MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));
}
 return this.memcahcedClient;
}
이렇게 하면 OK, 변동은 매우 간단하다.프로그램은 문제가 없을 뿐만 아니라, 단지 하나의 연결만 보장할 수 있다.
그러나 이 문제를 버리고 우리는 어떻게 단례 모델에서의 병발 문제를 해결할 것인가에 대해 깊이 생각해 볼 수 있다.
제가 요약한 바에 의하면 단례 모델이 병렬적으로 보내는 문제를 해결하려면 대략 세 가지 방식이 있습니다.
1. 지연 실례화를 사용하지 않고 미리 실례화한다.
프로그램 개요:

Public Class Singleton{
private static Singleton instance=new Singleton();
private Singleton(){};

public static Singleton getInstance(){
   return instance;
}
}

이렇게 할 때 jvm는 클래스를 불러올 때 바로 이 실례를 만들었기 때문에 이렇게 하는 전제 조건은 이 실례를 만드는 부담이 크지 않다. 나는 성능을 너무 많이 고려하지 않고 우리는 이 실례가 반드시 사용될 것이라고 확인한다.사실 내 앞의 코드도 이 방식을 충분히 사용할 수 있다.

MemcachedClientFactory{
private MemcachedConnectionBuilder memcachedConnectionBuilder;
private String servers;
private static MemcachedClient memcachedClien= new
MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));

private MemcachedClientFactory(){
}

private MemcachedClientFactory(MemcachedConnectionBuilder memcachedConnectionBuilder, String servers){
 this. memcachedConnectionBuilder= memcachedConnectionBuilder;
 this.servers=servers;
 }

public static MemcachedClient createClient(){
 return this.memcahcedClient;
}
}
}

그러나 문제가 없는 것 같지만, 누군가가memcachedClient를 잘못 호출하면 위험이 있다.shutdown () 방법, 모든 프로그램이 새로운memcachedClient를 재생할 수 없습니다.물론 극단적인 상황이지만 코드의 건장을 위해 다시 바꿀 수 있다.

public static MemcachedClient createClient(){
if(memcachedClient==null){
this.memcahcedClien= new MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));
}
return this.memcahcedClient;
}
2. synchronized 키워드를 사용합니다.
이렇게 하면 동기화 문제를 보장할 수 있지만synchronized를 사용하는 비용이 매우 크고 성능에 심각한 영향을 미칠 수 있다는 것을 우리는 알고 있다. 따라서 이 전제를 사용하면 이 방법을 자주 사용하지 않거나 이 instance를 만드는 비용이 특별히 크지 않을 것을 확인하는 것이다.개선이 가능한지 아래를 보십시오.
3. "이중 검사 잠금"을 사용하여 getInstance에서 동기화 사용

public Class Singleton{
private volatile static Singleton instance;

private Singleton(){};
public static Singleton getInstance(){
 if(instance==null){
  synchronized (Singleton.class){
 if(instance==null){
 instance=new Singleton();
}
}

}
return instance;
}
}

좋은 웹페이지 즐겨찾기