프로젝트 용 동적 버퍼가있는 비 차단 채널이 필요하므로이 코드를 작성했습니다. 여기 Go에서 선택 문의 외부 조건을 이동할 때이 교착 상태가 발생하는 이유
는 유형 선언입니다 ://receiver is the receiver of the non blocking channel
type receiver struct {
Chan <-chan string
list *[]string
mutex sync.RWMutex
}
//Clear sets the buffer to 0 elements
func (r *receiver) Clear() {
r.mutex.Lock()
*r.list = (*r.list)[:0]
r.mutex.Unlock()
//Discards residual content
if len(r.Chan) == 1 {
<-r.Chan
}
}
생성자 :
//NewNonBlockingChannel returns the receiver & sender of a non blocking channel
func NewNonBlockingChannel() (*receiver, chan<- string) {
//Creates the send and receiver channels and the buffer
send := make(chan string)
recv := make(chan string, 1)
list := make([]string, 0, 20)
r := &receiver{Chan: recv, list: &list}
go func() {
for {
//When the receiver is empty sends the next element from the buffer
if len(recv) == 0 && len(list) > 0 {
r.mutex.Lock()
recv <- list[len(list)-1]
list = list[:len(list)-1]
r.mutex.Unlock()
}
select {
//Adds the incoming elements to the buffer
case s := <-send:
r.mutex.Lock()
list = append(list, s)
r.mutex.Unlock()
//default:
}
}
}()
return r, send
}
그리고 메인의 장난감 시험 :
func main() {
recv, sender := NewNonBlockingChannel()
//send data to the channel
go func() {
for i := 0; i < 5; i++ {
sender <- "Hi"
}
time.Sleep(time.Second)
for i := 0; i < 5; i++ {
sender <- "Bye"
}
}()
time.Sleep(time.Millisecond * 70) //waits to receive every "Hi"
recv.Clear()
for data := range recv.Chan {
println(data)
}
}
나는 그것을 테스트하고 교착 상태가에서 일어난 보낸 사람으로부터받은 선택문 "사례 : = < 보내기 - : 나는 선택 문 모두에 다음 버퍼링 된 문자열을 전송하는 조건 블록을 이동할 때는 "하지만 완벽하게 작동합니다 :
go func() {
for {
select {
//Adds the incoming elements to the buffer
case s := <-send:
r.mutex.Lock()
list = append(list, s)
r.mutex.Unlock()
default:
//When the receiver is empty sends the next element from the buffer
if len(recv) == 0 && len(list) > 0 {
r.mutex.Lock()
recv <- list[len(list)-1]
list = list[:len(list)-1]
r.mutex.Unlock()
}
}
}
}()
나는 이유를 알고 싶습니다.
관용적 인 Go를 원하면 채널과 잠금을 혼합하지 않아야합니다. * 공유 메모리로 통신하지 마십시오. 대신 통신을 통해 메모리를 공유하십시오. * https://blog.golang.org/share-memory-by-communicating –
하지만 슬라이스에 액세스하는 동안 스레드 안전을 위해 잠금 장치가 필요합니다. 서비스의 특성 때문에 비 차단 채널이 필요하므로 슬라이스를 데이터 버퍼로 사용하기로 결정했습니다. –