Golang 단일 모드 최적 실천

2918 단어 독서 노트

단일 모드


단례 모델은 자주 사용하는 소프트웨어 디자인 모델로 사용 과정에서 단례 대상의 유형은 하나의 실례만 있다.단일 모드를 사용하면 1 메모리 등 자원을 절약할 수 있다. 예를 들어 윈도우즈 운영체제의 자원 관리자는 하나면 충분하다.2 설정 관리를 편리하게 한다. 예를 들어 서버의 설정 정보는 한 파일에 저장되고 설정 정보는 하나의 실례로 통일적으로 읽히며 입장하는 다른 대상은 이 실례로 설정 정보를 얻는다.

단례 모델 흔한 쓰기 분석


1. 인스턴스 1


아래의 코드에 무슨 문제가 있는지 학교에서 우리가 쓴 코드는 바로 아래와 같다. 별 문제가 없는 것 같지만 공업 실천에서 문제가 있다. 여러 라인의 각도에서 생각하면 아래의 코드는 비라인이 안전하다는 것을 알 수 있다. 만약에 두 라인이 모두 NewInstance1 함수를 호출하고 있다면 라인 A는if instance==nil로 실행된 후에 cpu에서 라인 B로 전환해서 라인 B가 실행될 때까지 라인 B가 실행된다.이 때 instance는 이미 실례화되었습니다. cpu가 라인 A로 되돌아갈 때 instance에 대해 실례화 작업을 실행합니다. 이 때 메모리에 Instance의 두 가지 실례가 있습니다. 하나의 정의에 어긋납니다.
type Instance struct{}

//     
func NewInstance1() *Instance {
	if instance == nil {
		instance = &Instance{}
	}
	return instance
}


2. 인스턴스 2


실례1은 비선정이 안전하기 때문에 자연히 인스타그램 실례화 잠금 조작에 대한 생각이 든다. 예를 들어 아래의 실례2와 같이 여러 개의 선정이 뉴인스타그램2를 실행할 때 직렬이기 때문에 실례1에 문제가 생기지 않는다. 그러나 이런 문법이 가장 좋은가. 성능 측면에서 보면 가장 좋은 것이 아닐까?New Instance2를 실행할 때 직렬로 되어 있어 효율에 영향을 받을 수 있습니다. 개선 조치가 있습니까?
var lock sync.Mutex

//lock-check  
func NewInstance2() *Instance {
	lock.Lock()
	defer lock.Unlock()
	if instance == nil {
		instance = &Instance{}
	}
	return instance
}

인스턴스 3


실례3은 선판단 방식을 사용하는데 instance가 이미 실례화되면 바로 되돌아오면 된다.실례화되지 않으면 자물쇠를 채워 실례를 만듭니다. 즉 실례 2를 실행합니다.이렇게 하면 동시에 집행할 수 있다.위의 실례2는 먼저lock이check방식에 있고 약칭lock-check모드라고 하는데 실례는check-lock-check모드라고 부른다.계속 생각해 봐요. 실례3에 문제가 있을까요?if instance==nil은 원자 조작입니까?
//check-lock-check  
func NewInstance3() *Instance {
	if instance == nil {
		lock.Lock()
		if instance == nil {
			instance = &Instance{}
		}
		lock.Unlock()
	}
	return instance
}

실례


실례 3 비교 조작이 비원자 조작이라면 이 문장을 비교 원자 조작으로 바꾸고golang은 원자 조작package atomic을 제공하여 uint32 변수를 신청하여 표시한다. 만약에 1이면 이미 실례화된 것이고 0이면 실례화된 것이다.실례 4는 이미 훌륭합니다. 골랑에서 더 좋은 방법이 있다면,
var initlized uint32

//check-lock-check
func NewInstance4() *Instance {
	if atomic.LoadUint32(&initlized) == 1 {
		return instance
	}

	lock.Lock()
	defer lock.Unlock()

	if initlized == 0 {
		instance = &Instance{}
		atomic.StoreUint32(&initlized, 1)
	}
	return instance
}


인스턴스 5


Golang에서, atomic 패키지에sync를 제공합니다.원스 타입, 이 타입은 Do 방법이 있는데 한 번만 실행할 수 있기 때문에 실례화 방법을 Do에 넣고 한 번만 실례화하는 완벽한 방법이기 때문에 실례 5가 최선의 실천 방법이다.
//best
func NewInstance5() *Instance {
	if instance == nil {
		once.Do(func() {
			instance = &Instance{}
		})
	}
	return instance
}

분석 총결


4
  • 코드를 쓸 때 정확성을 최우선으로 하고 성능 최적화를 고려해야 한다. 실례 1과 실례 3은 정확성에 있어서 보증이 없다

  • 4
  • 그 다음은 성능 최적화를 고려하는 것이다. 더 좋은 방법이 있는지, 예를 들어 실례2의 성능이 우호적이지 않으면 실례4는 실례2보다 향상되고 실례5는 가장 좋은 실천 방법이다

  • 4
  • 물론 실례 3 방법은 init 함수에 넣고 호출할 수 있습니다. 프로세스가 시작된 후에 다시 사용해도 문제가 없습니다. 왜냐하면 instance는 이미 실례화되었기 때문입니다
  • 좋은 웹페이지 즐겨찾기