Notice
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
- 솔리디티
- 인센티브 기반 커뮤니티
- 프록시패턴
- 트러블슈팅
- 투표
- 배팅
- 스테이트머신패턴
- 업그레이더블 컨트랙트
- 토큰노믹스
- 팀 프로젝트
- 재진입
- 회로차단
- 옵저버패턴
- 웹툰
- 코드스테이츠
- 부트캠프
- 팩토리패턴
- 일시정지
- 디자인 패턴
- git commit
- 코드리뷰
- RBAC
- 싱글톤패턴
- 멀티시그
- 블록체인
- git add
- solidity
- github
- github 에러
Archives
- Today
- Total
보다 더 생생한 기록
[GO] once.Do() + 데드락 본문
once.Do()
go package 공식문서 중 sync 패키지 내에 있는 Once.Do 의 형태는 다음과 같다.
func (o *Once) Do (f func()) : f 함수를 한번만 실행
그 밑에 다음과 같은 코멘트가 붙어있다.
"no call to Do returns until the one call to f returns, if f causes Do to be called, it will deadlock."
: f 함수에 대한 한 번의 호출이 반환 될 때가지 Do 함수에 대한 호출이 반환되지 않습니다.
즉, 우리가 파라미터로 넘겨준 함수 f가 Do 함수를 다시 한번 호출하게 된다면 데드락이 발생
∵ Do 함수는 넘겨준 함수가 끝날때까지 종료되지 않기 때문
Code Review - DeadLock
이전에 작성했던 코드를 보면
func Blockchain() *blockchain {
once.Do(func() {
b = &blockchain{
Height: 0,
}
checkpoint := db.Checkpoint()
if checkpoint == nil {
b.AddBlock()
} else {
b.restore(checkpoint)
}
})
return b
}
여기서 Do를 사용하는 상황에서 DeadLock이 발생하고, 무한으로 즐기는 로딩창이 시작된다.
Do안의 코드가 참조한 메서드 AddBlock의 세부코드를 보면
func (b *blockchain) AddBlock() {
block := createBlock(b.NewestHash, b.Height+1)
b.NewestHash = block.Hash
b.Height = block.Height
b.CurrentDifficulty = block.Difficulty
persistBlockchain(b)
}
이렇게 되어있는데 여기서 사용하는 createBlock를 한번 더 들어가 보면
func createBlock(prevHash string, height int) *Block {
block := &Block{
Hash: "",
PrevHash: prevHash,
Height: height,
Difficulty: difficulty(Blockchain()),
Nonce: 0,
}
block.mine()
block.Transaction = Mempool.TxToConfirm()
block.persist()
return block
}
위와 같다. 여기서 6번째 라인을 보면 value값에서 Blockchain()을 호출하고 있는 것이 보인다.
결국 한 바퀴 돌아와 맨 처음 Blockchain을 다시 부르는 것인데,
이는 아까 코멘트로 달려있던 "no call to Do returns until the one call to f returns, if f causes Do to be called, it will deadlock." 에 부합하다. 이래서 Deadlock이 발생한 것이었다.
Trouble Shooting
이를 해결하기 위해, createBlock의 형태를 변경하였다.
func createBlock(prevHash string, height int) *Block
에서
func createBlock(prevHash string, height, diff int) *Block
기존 difficulty(Blockchain())을 대체하는, diff는 Blockchain()을 호출하는 것이 아닌 다른 방식으로 끌고 오게 되면서 Deadlock이 해결되었다.
'Go' 카테고리의 다른 글
[GO] 중첩반복문 탈출 방법 : label (0) | 2023.09.13 |
---|---|
[GO] Method VS Function 선언 선택 공식, 함수 또는 메서드가 어떤 역할 하는지 선언만 보고 간단하게 파악하기 (0) | 2023.09.08 |
[GO] [코드리뷰] 블록체인 구축 코드 리뷰 (PoW) - (2) (0) | 2023.09.02 |
[GO] [코드리뷰] 블록체인 구축 코드 리뷰 - (1) (0) | 2023.08.31 |
[GO] go get VS go install (zsh: command not found) (0) | 2023.08.30 |