内存分配 、同步、互斥

malloc()

c 语言的malloc是glibc函数,其实际对应的系统调用是brk()函数(实际上是syscall 1)。glibc对brk系统调用进行封装,然后抽象出malloc函数,提供给linux开发者使用。brk函数对应的是堆操作;

进程的空间 = 系统空间+用户空间(栈:局部变量和函数参数,寄存器+堆:动态内存,开发者分配+.bss+data常量区+text代码段)

32位系统只能寻址4G空间,64位则是128G; 

 

 

(1)new、delete 是操作符,只能在C++中使用。malloc、free是函数,可以覆盖,C、C++中都可以使用。
(2)new 自动计算需要分配的空间大小,可以调用对象的构造函数,对应的delete调用相应的析构函数。malloc仅仅分配内存,free仅仅回收内存,并不执行构造和析构函数
(3)new 类型安全、返回的是某种数据类型指针,malloc 非类型安全、返回的是void指针。

 

TCMalloc

TCMalloc全称Thread-Caching Malloc,即线程缓存的malloc,实现了高效的多线程内存管理,用于替代系统的内存分配相关的函数(malloc、free,new,new[]等)。TCMalloc是gperftools的一部分

TCMalloc内存分配算法

按照所分配内存的大小,TCMalloc将内存分配分为三类:

  • 小对象分配,(0, 256KB]  
  • 中对象分配,(256KB, 1MB]
  • 大对象分配,(1MB, +∞)

简要介绍几个概念,Page,Span,PageHeap:

ThreadCache:每个线程的单独缓存,由FreeList按Size Class(8KB/16KB...256KB)存储的空闲对象链表;线程内部取用回收不需要加锁所以很快;

CentralCache: 所有线程的公用缓存,由 CentralFreeList按Size Class(8KB/16KB...256KB)存储的空闲对象链表;供各个线程的 ThreadCache 取用,所以取用或回收对象是需要加锁的;

PageHeap:CentralCache不够时向 PageHeap申请一块内存,PageHeap使用sbrk或mmap向系统申请新的内存以生成新的span;PageHeap内部根据内存块(span)采取不同的缓存策略:128个 span以内,每个 size 用链表缓存,超过128个 page 的 span,存储与一个有序的 set 里,PageHeap取用或释放内存时需要加 spinlock,

互斥和同步

同步:任务协调同步,比如 A 依赖 B

互斥:访问共享资源

互斥锁(mutex)

上锁(lock)和解锁(unlock);原子性(原子操作)、唯一性、非繁忙等待(A 线程锁定互斥量,则 B 线程试图锁时会被挂起即不占用 cpu资源,直至互斥量解锁唤醒B线程)

#include <pthread.h>

#include <time.h>

// 初始化一个互斥锁。

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);

 

// 对互斥锁上锁,若互斥锁已经上锁,则调用者一直阻塞,

// 直到互斥锁解锁后再上锁。

int pthread_mutex_lock(pthread_mutex_t *mutex);

 

// 调用该函数时,若互斥锁未加锁,则上锁,返回 0;

// 若互斥锁已加锁,则函数直接返回失败,即 EBUSY。

int pthread_mutex_trylock(pthread_mutex_t *mutex);

 

// 当线程试图获取一个已加锁的互斥量时,pthread_mutex_timedlock 互斥量

// 原语允许绑定线程阻塞时间。即非阻塞加锁互斥量。

int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,const struct timespec *restrict abs_timeout);

 

// 对指定的互斥锁解锁。

int pthread_mutex_unlock(pthread_mutex_t *mutex);

 

// 销毁指定的一个互斥锁。互斥锁在使用完毕后,

// 必须要对互斥锁进行销毁,以释放资源。

int pthread_mutex_destroy(pthread_mutex_t *mutex);


条件变量(同步)

条件变量用来自动阻塞一个线程,直 到某特殊情况发生为止

条件变量使用过程:1. 初始化:2. 等待条件成立3. 激活条件变量:4. 清除条件变量:

#include <pthread.h>

// 初始化条件变量

int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);

 

// 阻塞等待

int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);

 

// 超时等待

int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);

 

// 解除所有线程的阻塞

int pthread_cond_destroy(pthread_cond_t *cond);

 

// 至少唤醒一个等待该条件的线程

int pthread_cond_signal(pthread_cond_t *cond);

 

// 唤醒等待该条件的所有线程

int pthread_cond_broadcast(pthread_cond_t *cond);

 

读写锁

#include <pthread.h>

// 初始化读写锁

int pthread_rwlock_init(pthread_rwlock_t *rwlock,

                        const pthread_rwlockattr_t *attr);

 

// 申请读锁

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock );

 

// 申请写锁

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock );

 

// 尝试以非阻塞的方式来在读写锁上获取写锁,

// 如果有任何的读者或写者持有该锁,则立即失败返回。

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

 

// 解锁

int pthread_rwlock_unlock (pthread_rwlock_t *rwlock);

 

// 销毁读写锁

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

 

自旋锁

锁的持有时间比较短,或者说小于2次上下文切换的时间。

spinlock又称自旋锁,线程通过busy-wait-loop的方式来获取锁,任时刻只有一个线程能够获得锁,其他线程忙等待直到获得锁

spinlock在多处理器多线程环境的场景中有很广泛的使用,一般要求使用spinlock的临界区尽量简短,这样获取的锁可以尽快释放,以满足其他忙等的线程。Spinlock和mutex不同,spinlock不会导致线程的状态切换(用户态->内核态),但是spinlock使用不当(如临界区执行时间过长)会导致cpu busy飙高。

信号量(同步和互斥)

信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。

编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于 0 时,则可以访问,否则将阻塞。PV 原语是对信号量的操作,一次 P 操作使信号量减1,一次 V 操作使信号量加1。
 

#include <semaphore.h>

// 初始化信号量

int sem_init(sem_t *sem, int pshared, unsigned int value);

 

// 信号量 P 操作(减 1)

int sem_wait(sem_t *sem);

 

// 以非阻塞的方式来对信号量进行减 1 操作

int sem_trywait(sem_t *sem);

 

// 信号量 V 操作(加 1)

int sem_post(sem_t *sem);

 

// 获取信号量的值

int sem_getvalue(sem_t *sem, int *sval);

 

// 销毁信号量

int sem_destroy(sem_t *sem);

转载于:https://my.oschina.net/u/347414/blog/3038872

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值