Golang中重新open 已经被close的chan管道

GoWKH · · 2306 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

最近忽发奇想,在Golang中怎么把,已经关闭的管道再次打开。这样就避免了,每次都要make一个新的chan,节省内存申请和GC的时间,查看go的源代码,经过简单地摸索后,实现了,示例代码如下。
func TestUnsafe(t *testing.T) {
	c1 = make(chan struct{}, 10)
	c1 <- struct{}{}
	<-c1
	close(c1)
	p := (*unsafe.Pointer)(unsafe.Pointer(&c1))
	c := (*hchan)(*p)
	c.closed = 0//打开被关闭的chan
	c1 <- struct{}{}
	<-c1
}
func TestSafe(t *testing.T) {
	c1 = make(chan struct{}, 10)
	c1 <- struct{}{}
	<-c1
	close(c1)
	p := (*unsafe.Pointer)(unsafe.Pointer(&c1))
	c := (*hchan)(*p)
	atomic.CompareAndSwapUint32(&c.closed, 1, 0) //打开被关闭的chan
	c1 <- struct{}{}
	<-c1
} 

最终代码 发布到 github.com/yireyun/go-openc,有兴趣的朋友可以看看。

这种做法最大的缺点是如果go的runtime的数据结构发生变化,将不再可行。因此增加了在init方法中检测的go内核数据结构是否发生变化的代码,性能测试结果如下。

BenchmarkMakeCloseChan-4       	20000000	  90.9 ns/op
--- BENCH: BenchmarkMakeCloseChan-4(每次新建在关闭的性能)
go1.7.4, Times:         1, use:             0s         0s/op
go1.7.4, Times:       100, use:             0s         0s/op
go1.7.4, Times:     10000, use:        998.3µs       99ns/op
go1.7.4, Times:   1000000, use:      91.0664ms       91ns/op
go1.7.4, Times:  20000000, use:     1.8185449s       90ns/op
BenchmarkCloseOpenChan-4       	50000000	  29.5 ns/op
--- BENCH: BenchmarkCloseOpenChan-4(非安全打开的性能)
go1.7.4, Times:         1, use:             0s         0s/op
go1.7.4, Times:       100, use:             0s         0s/op
go1.7.4, Times:     10000, use:             0s         0s/op
go1.7.4, Times:   1000000, use:      28.5199ms       28ns/op
go1.7.4, Times:  50000000, use:      1.473497s       29ns/op
BenchmarkCloseOpenChanSync-4   	30000000	  44.9 ns/op
--- BENCH: BenchmarkCloseOpenChanSync-4(安全打开的性能)
go1.7.4, Times:         1, use:             0s         0s/op
go1.7.4, Times:       100, use:             0s         0s/op
go1.7.4, Times:     10000, use:        498.2µs       49ns/op
go1.7.4, Times:   1000000, use:      47.5278ms       47ns/op
go1.7.4, Times:  30000000, use:     1.3479236s       44ns/op
PASS
ok  	github.com/yireyun/go-openc	8.235s

有疑问加站长微信联系(非本文作者)

本文来自:知乎专栏

感谢作者:GoWKH

查看原文:Golang中重新open 已经被close的chan管道

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2306 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传