【发布时间】:2016-12-03 17:23:30
【问题描述】:
我在 Go 中看到了一些使用切片的 FIFO 队列实现。当项目退出队列时,是否可以在不重新分配底层数组的情况下释放此内存?如果这没有发生,在我看来,队列会泄漏大量内存。这就是我的意思:
type queue
{
[]int
int head
}
func (q *queue) enqueue(val int) {
q = append(q, val)
}
func (q *queue) dequeue() int {
return (*q)[q.head++]
}
在多次调用 enqueue/dequeue 之后,位于 slice 下的数组的低索引不再可用,但我也不确定如何释放它们。有人可以指出一个不使用指针的正确队列实现,并且不会像这样泄漏内存或有性能问题吗?或者,也将赞赏这可能如何工作的描述。
谢谢, 普拉门
【问题讨论】:
-
首先,如果你想要并发,你需要在这些方法中使用互斥锁,这已经开始有味道了。我使用 Channels 处理队列,因为通道基本上只是堆栈副本。 GC 会在使用后清理它们。
-
对线程安全不感兴趣,只对这个问题的内存管理感兴趣。从我读到的内容来看,使用通道来实现队列是一个坏主意,因为它们与常规调度密切相关,并且可以挂起整个程序。在最好的情况下,它们效率低下。这是我读过的书:amazon.com/…
-
上面的代码不是实现,只是为了说明我的问题
-
实现的权衡是您必须决定的。这个例子似乎是故意泄漏内存,所以我不确定它试图说明什么时候你可以很容易地切掉出队的值。如果您想将 std 库堆用作示例,也经常将其用作优先级队列。
-
如果您对内存管理感兴趣,可以看看this answer 及其 cmets。不确定它实际上会对您有多大帮助,但这通常是一个好处,因为您通常不希望仅仅添加一个值而导致执行时间损失......
标签: go data-structures queue slice