golang 有缓冲channel full不阻塞线程
解决方案一:每次向channel进行写操作前,判断channel长度
note:获取channel长度并不是线程安全的,所以要加锁进行操作。加锁会影响性能,尤其在高并发情况下,会导致大量的线程挂起。此方案不推荐。
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
var tlock sync.Mutex
var testChan = make(chan int, 10)
func f(name string) {
defer func() {
wg.Done()
fmt.Printf("%s :done\n", name)
}()
for i := 0; i < 5; i++ {
time.Sleep(10 * time.Microsecond)
tlock.Lock()
tlen := len(testChan)
if tlen == 10 {
fmt.Printf("%s :channel is full\n", name)
tlock.Unlock()
break
}
testChan <- i
fmt.Printf("%s :%d\n", name, i)
tlock.Unlock()
}
}
func main() {
t := []string{"A", "B", "C", "D"}
for i := 0; i < 4; i++ {
wg.Add(1)
go f(t[i])
}
wg.Wait()
}
解决方案二:使用select语句
当case被阻塞的时候,select会执行default语句。
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
var testChan = make(chan int, 10)
func f(name string) {
defer func() {
wg.Done()
fmt.Printf("%s :done\n", name)
}()
for i := 0; i < 5; i++ {
time.Sleep(10 * time.Microsecond)
select {
case testChan <- i:
fmt.Printf("%s :%d\n", name, i)
default:
fmt.Printf("%s :channel is full\n", name)
return
}
}
}
func main() {
t := []string{"A", "B", "C", "D"}
for i := 0; i < 4; i++ {
wg.Add(1)
go f(t[i])
}
wg.Wait()
}
网友评论