多线程的使用

一、线程的基本概念和用法

https://blog.csdn.net/zgege/article/details/79912418

二、线程的同步 

https://blog.csdn.net/zgege/article/details/79992333

线程同步的机制包括:互斥锁,读写锁,自旋锁,条件变量,信号量,异步信号

读写锁:

读写锁与互斥量类似,不过读写锁允许更高的并行性。适用于读的次数大于写的次数的数据结构。

一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁

自旋锁:

互斥量阻塞线程的方式是使其进入睡眠,而自旋锁是让线程忙等,即不会使其睡眠,而是不断循判断自旋锁已经被解锁。

适用于占用自旋锁时间比较短的情况。

条件变量:

给多个线程提供一个会合的场所,条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定条件的发生;

信号量和异步信号:

http://www.cnblogs.com/wanghuaijun/p/9532644.html

介绍一下POSIX(POSIX标准定义了操作系统应该为应用程序提供的接口标准,换句话说,为一个POSIX兼容的操作系统编写的程序,应该可以在任何其它的POSIX操作系统(即使是来自另一个厂商)上编译执行。)的信号量机制,定义在头文件/usr/include/semaphore.h

1)初始化一个信号量:sem_init()

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

pshared为0时表示该信号量只能在当前进程的线程间共享,否则可以进程间共享,value给出了信号量的初始值。

2)阻塞线程

sem_wait(sem_t* sem)直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少;sem_trywait(sem_t* sem)是wait的非阻塞版本,它直接将sem的值减一,相当于P操作。

3)增加信号量的值,唤醒线程

sem_post(sem_t* sem)会使已经被阻塞的线程其中的一个线程不再阻塞,选择机制同样是由线程的调度策略决定的。相当于V操作。

3)释放信号量资源

sem_destroy(sem_t* sem)用来释放信号量sem所占有的资源

复制代码

pthread_mutex_t mutex;
sem_t full,empty;

void producer(void* arg){
    while(1){
    sem_wait(&empty);//need to produce. the the empty of resource need minus 1
    pthread_mutex_lock(&mutex);
    ...//produce a resource
    pthread_mutex_unlock(&mutex);
    sem_post(&full); //have produced a resource, the the full of resource need add 1
    }
}
void consumer(void* arg){
    while(1){
    sem_wait(&full);
    pthread_mutex_lock(&mutex);
    ...//consume a resource
    pthread_mutex_unlock(&mutex);
    sem_post(&empty); 
    }
}

三、线程的属性 

 属性的初始化以及销毁

#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);

detachstate属性的分离状态:

如果对某个线程的终止状态不感兴趣的话,可以使用pthread_detach函数将操作系统在线程退出时回收

它所占用的资源;

detachstate有两个合法值:

PTHREAD_CREATE_DETACHED以分离状态启动线程;

                                            PTHREAD_CREATE_JOINABLE正常启动线程;

int pthread_attr_getdetachstate(const pthread_attr_t *restrict attr, int *detachstate);
int pthread_attr_setdetachstate(const pthread_attr_t *attr, int *detachstate);

stacksize属性:

如果希望改变默认栈的大小,又不想自己处理线程栈的分配问题,这时使用pthread_attr_setstacksize函数非常有用;

int pthread_attr_getstacksize(const pthread_attr_t *restrict attr, size_t *restrict stacksize);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

 stackaddr属性:

  1. 对于进程来说,虚拟地址的大小是固定的,因为进程中只有一个栈,所以它的大小通常不是问题;但对于线程来说,同样大小的虚拟地址空间必须被所有的线程栈共享,如果应用程序使用了很多线程,以至于这些线程栈的累计大小超过了可用的虚拟地址空间,就需要减小默认的线程栈的大小;
  2. 栈消耗较大的两种情况:线程调用的函数分配了大量的自动变量、调用的函数涉及很深的栈帧;
  3. 如果线程的虚拟地址空间用完了,可以使用malloc或者mmap来为替代的栈分配空间;
int pthread_attr_getguardsize(const pthread_attr_t *restrict attr, size_t *restrict guardsize);
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);

 guardsize属性:

控制着线程栈末尾之后用以避免栈溢出的扩展内存的大小;

int pthread_attr_getstack(const pthread_attr_t *restrict attr, void **restrict stackaddr, size_t *restrict stacksize);
int pthread_attr_setstack(const pthread_attr_t *attr, void *stackaddr, size_t stacksize);

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值