Go语言取整 go语言struct( 二 )


3.MCentral:作为MHeap和MCache的承上启下的连接 。承上,从MHeap申请MSpan;启下,将MSpan划分为各种尺寸的对象提供给MCache使用 。
type MCentral struct
{
lock mutex;
sizeClass int32;
noempty mSpanList;
empty mSpanList;
int32 nfree;
……
};
type mSpanList struct {
first *mSpan
last*mSpan
};
sizeclass: 也有成员 sizeclass,用于将MSpan进行切分 。
lock: 因为会有多个 P 过来竞争 。
nonempty: mspan 的双向链表,当前 mcentral 中可用的 mSpan list 。
empty: 已经被使用的,可以认为是一种对所有 mSpan 的 track 。MCentral存在于MHeap内 。
给对象 object 分配内存的主要流程:
1.object size32K,则使用 mheap 直接分配 。
2.object size16 byte , 使用 mcache 的小对象分配器 tiny 直接分配 。(其实 tiny 就是一个指针,暂且这么说吧 。)
3.object size16 bytesize =32K byte 时,先使用 mcache 中对应的 size class 分配 。
4.如果 mcache 对应的 size class 的 span 已经没有可用的块 , 则向 mcentral 请求 。
5.如果 mcentral 也没有可用的块,则向 mheap 申请,并切分 。
6.如果 mheap 也没有合适的 span,则想操作系统申请 。
tcmalloc内存分配器介绍
tcmalloc(thread-caching mallo)是google推出的一种内存分配器 。
具体策略:全局缓存堆和进程的私有缓存 。
1.对于一些小容量的内存申请试用进程的私有缓存 , 私有缓存不足的时候可以再从全局缓存申请一部分作为私有缓存 。
2.对于大容量的内存申请则需要从全局缓存中进行申请 。而大小容量的边界就是32k 。缓存的组织方式是一个单链表数组,数组的每个元素是一个单链表 , 链表中的每个元素具有相同的大小 。
golang语言中MHeap就是全局缓存堆,MCache作为线程私有缓存 。
在文章开头说过 , 内存池就是利用MHeap实现,大小切分则是在申请内存的时候就做了,同时MCache分配内存时,可以用MCentral去取对应的sizeClass,多线程管理方面则是通过MCache去实现 。
总结:
1.MHeap是一个全局变量 , 负责向系统申请内存,mallocinit()函数进行初始化 。如果分配内存对象大于32K直接向MHeap申请 。
2.MCache线程级别管理内存池 , 关联结构体P,主要是负责线程内部内存申请 。
3.MCentral连接MHeap与MCache的,MCache内存不够则向MCentral申请,MCentral不够时向MHeap申请内存 。
go语言里怎么把整数变成负数取相反数?取一个数的相反数,可以用数学运算来实现:-1 * x的结果就是x的相反数 。
go的uint64转换成java的哪种类型Golang 和java/c不同 , Go在不同类型的变量之间赋值时需要显式转换 。也就是说Golang中数据类型不能自动转换 。
基本语法
表达式T(v))将值v 转换为类型T
T∶就是数据类型,比如int32,int64 , float32等等
v∶ 就是需要转换的变量
var i int = 100
var b float64 = float64(i)
var c int64 = int64(b)
fmt.Printf("b=%f,c=%d",b,c)
b=100.000000,c=100
登录后复制
细节说明
1)Go中,数据类型的转换可以是从表示范围小-表示范围大,也可以范围大一范围小
2) 被转换的是变量存储的数据(即值) , 变量本身的数据类型并没有变化!
3) 在转换中,比如将 int64 转成int8,编译时不会报错,只是转换的结果是按溢出处理 , 和
我们希望的结果不一样 。(在转换的时候需要注意范围)
var a int64 = 10000000
var b int8 = int8(a)
fmt.Printf("%d",b)

推荐阅读