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

  1. 延迟函数的参数在defer语句出现时就已经确定了。
  2. 延迟函数按后进先出顺序执行。
  3. 延迟函数可能操作主函数的具名返回值。

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个读者

参考