1.线程分离属性:
线程结束后,自动回收线程空间
pthread_attr_init
int pthread_attr_init(pthread_attr_t *attr);
功能:
线程属性初始化
pthread_attr_destroy
int pthread_attr_destroy(pthread_attr_t *attr);
功能:
线程属性销毁
pthread_attr_setdetachstate
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
功能:
设置分离属性
PTHREAD_CREATE_DETACHED 分离属性
PTHREAD_CREATE_JOINABLE 加入属性(默认)
eg:
void *threadfun1(void *arg) //线程执行的函数入口1
{
printf("线程1(TID:%#x)开始运行!\n",(unsigned int)pthread_self());
return NULL;
}
void *threadfun2(void *arg) //线程执行的函数入口2
{
printf("线程2(TID:%#x)开始运行!\n",(unsigned int)pthread_self());
return NULL;
}
void *threadfun3(void *arg) //线程执行的函数入口3
{
printf("线程3(TID:%#X)开始运行!\n",(unsigned int)pthread_self());
return NULL;
}
int main(void)
{
int ret = 0;
int i = 0;
pthread_t tid[3];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
void *(*th[10])(void *) = {threadfun1,threadfun2,threadfun3}; //函数指针数组
for(i=0;i<3;i++)
{
ret = pthread_create(&tid[i],&attr,th[i],NULL);
if(ret != 0)
{
perror("fail to pthread_create");
return -1;
}
}
pthread_attr_destroy(&attr);
while(1)
{
}
return 0;
}
2.互斥锁
作用:防止资源竞争(线程的互斥)
多线程的全局变量,无脑加锁
函数接口:
1. pthread_mutex_init:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
功能:互斥锁的初始化
参数:mutex:互斥锁空间首地址
attr:互斥锁的属性(默认为NULL)
返回值:成功返回0 , 失败返回错误码
2.pthread_mutex_destroy:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:互斥锁的销毁
参数:mutex:互斥锁空间首地址
返回值:成功返回0 ,失败返回错误码
3.pthread_mutex_lock:
int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:上锁
4. pthread_mutex_unlock:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能:解锁
5.临界资源,临界区:
加锁解锁中间代码成为临界资源,临界区
同一时刻临界资源不能同时执行,只能执行其中一个临界资源代码
6.原子操作:
CPU最小的一次不能被任务调度打断的操作成为原子操作
7.互斥锁只能解决资源竞争的问题,无法同步代码(没有先后执行的顺序关系)
eg:
pthread_mutex_t lock; //全局变量 , 互斥锁的调用
int Num = 0;
void *threadfun1(void *arg)
{
while(1)
{
pthread_mutex_lock(&lock);
Num = 100;
pthread_mutex_unlock(&lock);
}
return NULL;
}
void *threadfun2(void *arg)
{
while(1)
{
pthread_mutex_lock(&lock); //互斥锁的打开,锁一个争夺变量的时候每一个线程的挣夺变两部分都要上锁,保证不会同时运行
Num = 200;
printf("Num = %d\n",Num);
pthread_mutex_unlock(&lock); //互斥所的关闭
}
return NULL;
}
int main(void)
{
pthread_t tid1;
pthread_t tid2;
pthread_mutex_init(&lock,NULL); //互斥锁的初始化
pthread_create(&tid1,NULL,threadfun1,NULL);
pthread_create(&tid2,NULL,threadfun2,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_mutex_destroy(&lock); //互斥锁的销毁,一定要在线程结束之后
}
3.死锁
概念:多线程操作互斥锁,导致多个线程均无法向下执行的状态称为死锁状态简称为死锁
死锁产生的四个必要条件:1.互斥条件 2.不可剥夺条件 3.请求保持 4.循环等待
避免产生死锁:1.pthread_mutex_trylock 替代 pthread_mutex_lock 2.加锁顺序保持一致
4.信号量
概念:信号量是一种资源,可以被初始化、申请、释放、销毁 --- P操作:申请资源,V操作:释放资源
1. sem_init
int sem_init(sem_t *sem, int pshared, unsigned int value);
功能:初始化信号量
参数:sem:信号量空间首地址
pshared: 0 一个进程中的所有线程间共享 ; 非0 进程间共享
value: 初始化的值
返回值:成功返回0;失败返回-1
2. sem_destroy:
int sem_destroy(sem_t *sem);
功能:信号量的销毁
参数:sem:信号量空间首地址
返回值:成功返回0 ; 失败返回-1
3. sem_wait:
int sem_wait(sem_t *sem);
功能:申请信号量
4. sem_post:
int sem_post(sem_t *sem);
功能:释放信号量
eg:线程的同步
char tmpbuff[4096] = {0}; //全局变量
sem_t sem_r; //定义“读”的信号量变量
sem_t sem_w; //定义“写”的信号量变量
void *thread1(void *arg)
{
while (1)
{
sem_wait(&sem_w); //申请“写”信号量
gets(tmpbuff);
sem_post(&sem_r); //释放“读”信号量
}
return NULL;
}
void *thread2(void *arg)
{
while (1)
{
sem_wait(&sem_r); //申请“读”信号量
printf("tmpbuff = %s\n", tmpbuff);
sem_post(&sem_w); //申请“写”信号量
}
return NULL;
}
int main(void)
{
pthread_t tid1;
pthread_t tid2;
sem_init(&sem_w, 0, 1); //设置信号量个数,写为一个,因为要先从终端写入tmpbuff中
sem_init(&sem_r, 0, 0); //读为0个,在写完未释放读的信号量个数时,不能读出打印
pthread_create(&tid1, NULL, thread1, NULL);
pthread_create(&tid2, NULL, thread2, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
sem_destroy(&sem_w);
sem_destroy(&sem_r);
return 0;
}