面试题答案
一键面试实现思路
- 内存块划分:将大块内存划分成固定大小的小块,这些小块就是我们内存池中的基本单位。
- 指针管理:使用指针来标记每个小块内存的位置以及是否被使用。
- 分配逻辑:遍历内存块链表,找到未使用的内存块,标记为已使用并返回其指针。
- 回收逻辑:将使用完的内存块标记为未使用,重新加入可用链表。
关键代码片段
package main
import (
"fmt"
"unsafe"
)
// 定义内存块大小
const blockSize = 1024
// 定义内存块结构体
type block struct {
next *block
used bool
}
// 定义内存池结构体
type MemoryPool struct {
head *block
}
// 创建新的内存池
func NewMemoryPool() *MemoryPool {
// 申请大块内存
rawMem := make([]byte, blockSize*10)
memPtr := (*block)(unsafe.Pointer(&rawMem[0]))
// 初始化内存块链表
for i := 0; i < 9; i++ {
memPtr.next = (*block)(unsafe.Pointer(uintptr(unsafe.Pointer(memPtr)) + blockSize))
memPtr.used = false
memPtr = memPtr.next
}
memPtr.next = nil
memPtr.used = false
return &MemoryPool{head: (*block)(unsafe.Pointer(&rawMem[0]))}
}
// 从内存池分配内存
func (mp *MemoryPool) Allocate() unsafe.Pointer {
current := mp.head
for current != nil {
if!current.used {
current.used = true
return unsafe.Pointer(current)
}
current = current.next
}
return nil
}
// 回收内存到内存池
func (mp *MemoryPool) Free(ptr unsafe.Pointer) {
if ptr == nil {
return
}
blockPtr := (*block)(ptr)
blockPtr.used = false
}
你可以使用以下方式调用:
func main() {
pool := NewMemoryPool()
ptr1 := pool.Allocate()
ptr2 := pool.Allocate()
fmt.Printf("Allocated ptr1: %v\n", ptr1)
fmt.Printf("Allocated ptr2: %v\n", ptr2)
pool.Free(ptr1)
fmt.Println("Freed ptr1")
newPtr := pool.Allocate()
fmt.Printf("New allocated ptr: %v\n", newPtr)
}