slice
slice[low:high:max]的len=high-low,cap=max-low
- 若max>capUnder(底层数组或切片的容量)会panic
- 若max省略则max=capUnder,当前slice的cap=capUnder-low
map
hmap有2^B个bucket,bucket存放哈希值冲突的键值对
每个bucket(bmap)对应哈希值低位相同的键,哈希值高8位将存入tophash数组。
data区键值对数据存放顺序是key/key/key/…value/value/value,可节省字节对齐带来的空间浪费。
每个bucket最多存8个键值对,再多就以开链法由overflow指针指向下一bucket。
扩容
负载因子=键数量/bucket数量,负载因子>6.5时触发扩容
增量扩容:倍增bucket数,逐步搬迁 等量扩容:bucket数不变,为了重新排列键值对,减少开链overflow的bucket数
iota
iota代表const声明块的行索引
defer
- 延迟函数的参数在defer语句出现时就已经确定了。
- 延迟函数按后进先出顺序执行。
- 延迟函数可能操作主函数的具名返回值。
return语句不是原子操作,实际执行过程为:设置返回值 -> 执行defer -> ret
mutex
type Mutex struct {
state int32
sema uint32
}state位:Waiter(29) Starving(1) Woken(1) Locked(1)
自旋相当于CPU的”PAUSE”指令,CPU对该指令什么都不做,当前实现的自旋时间是30时钟周期。
Woken状态用于加锁和解锁过程的通信。比如同一时刻,两个协程一个在加锁一个在解锁,加锁协程在自旋时把Woken置为1,通知解锁协程不必释放信号量了。
type RWMutex struct {
w Mutex // held if there are pending writers
writerSem uint32 // semaphore for writers to wait for completing readers
readerSem uint32 // semaphore for readers to wait for completing writers
readerCount int32 // number of pending readers
readerWait int32 // number of departing readers
}对写-写的互斥通过mutex完成,对读-写的互斥通过如下方式: 写者Lock()时,
- 把
readerCount-=rwmutexMaxReaders,这样将来读者RLock()时一看++readerCount<0就知前面有写者,自己要阻塞。 - 保存
readerWait=readerCount,将来读者RUnlock()时一看--readerCount<0就知后面有写者阻塞,则当--readerWait==0时唤醒写者。 写者Unlock()时, - 复原
readerCount+=rwmutexMaxReaders - 读者只能在后面,要唤醒
readerCount个读者