Linux系统编程:线程2:退出、回收、锁
任意一个线程调用exit都会导致进程结束,进程结束则线程不复存在,从main函数中执行return 操作这种也是进程结束,也会导致所有线程结束。如果是主线程调用pthread_exit函数,此时主线程的执行流结束了,但是进程并没有结束,此时进程会等所有子线程结束才会销毁。线程如果是可结合的,调用pthread_exit退出,调用pthread_join来回收资源,并且可以获得退出状态值。线程在该函
pthread_exit --> void pthread_exit(void *retval); #include <pthread.h>
功能:退出当前线程 -- 类似于进程中的exit
参数:@retval //退出状态值的地址
pthread_join --> int pthread_join(pthread_t thread, void **retval); #include <pthread.h>
功能:等待当前线程结束并回收资源,获得退出状态值 -- 类似于进程中的wait
参数:
- @thread 要等待的线程tid
- @retval 保存pthread exit 传递过来的退出状态的地址
返回值:
- 成功 返回0
- 失败 返回错误码
注意:
- 线程退出时可以传递退出状态值,但是实际上退出的是状态值对应的地址
- 如果是主线程调用pthread_exit函数,此时主线程的执行流结束了,但是进程并没有结束,此时进程会等所有子线程结束才会销毁
pthread_cancel --> int pthread_cancel(pthread_t thread); #include <pthread.h>
功能:
任意一个线程调用exit都会导致进程结束,进程结束则线程不复存在,从main函数中执行return 操作这种也是进程结束,也会导致所有线程结束
回收资源:
线程如果是可结合的,调用pthread_exit退出,调用pthread_join来回收资源,并且可以获得退出状态值
线程如果是可分离的pthread_detach
pthread_detach --> int pthread_detach(pthread_t thread); #include <pthread.h>
功能:将pthread线程标记为分离状态
参数:thread线程tid
返回值:成功 0 失败 返回错误码
如果一个线程被标记为可分离状态,此时该线程的资源在程序结束时会被系统自动回收,而且不需要别的线程pthread_join来回收
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
void *do_sth(void* arg)
{
static int ret = 99;
printf("do_sth\n");
// pthread_exit(&ret);
// pthread_exit("i am dead");
// return NULL;
// return &ret;
return "i am dead";
}
int main(int argc,const char* argv[])
{
pthread_t tid;
int ret = pthread_create(&tid,NULL,do_sth,NULL);
if(ret != 0)
{
errno = ret;
perror("pthread_create fail");
return -1;
}
printf("main————\n");
void *retval;
pthread_join(tid,&retval);
// printf("main retval : %d\n",*(int *)retval);
printf("main retval = %s\n",(char *)retval);
return 0;
}
进程VS线程——CPU调度执行最小单位VS资源管理的最小单位
进程:父子空间独立,在32位平台上,各自拥有4G内存
- 好:空间独立,安全性,稳定性好
- 坏:共享数据不方便——进程间通信
线程:线程共享了进程的资源
- 好:共享数据方便
- 坏:①数据的竞争——线程间的同步互斥手段解决
- ②安全性稳定性不如进程//eg:某个进程不小心写了一个段错误,其他线程也无法执行
线程库提供“互斥锁”:要使用临界资源,在使用前先上锁->使用公共资源->解锁
互斥访问 —— 独占使用,线程间同步互斥手段解决
临界资源 —— 多个线程要访问的公共资源
原子性操作
临界区 —— 访问临界资源的那段代码
pthread_mutex_init --> int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr); #include <pthread.h>
功能:初始化一把锁
参数:
- @mutex:要初始化哪一把锁
- @attr:锁的属性 NULL—表示普通锁 //普通锁:读写锁
返回值:
- 成功 返回0
- 失败 返回错误码
pthread_mutex_lock --> int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:加锁
参数:@mutex:要使用哪一把锁
返回值:
- 成功 返回0
- 失败 返回错误码
pthread_mutex_unlock --> int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能:解锁
参数:@mutex:要使用哪一把锁
返回值:
- 成功 返回0
- 失败 返回错误码
pthread_mutex_destroy --> int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:销毁锁
参数:@mutex:要使用的锁
返回值:
- 成功 返回0
- 失败 返回错误码
锁的颗粒度:越小越好
希望线程之间有序地进行
linux下的线程同步===》 信号量机制 ==》 semaphore. h posix sem_open ();
信号量的分类:
- 信号无名量 ==》线程间通信
- 有名信号量 ==》 进程间的通信
框架
- 信号量的定义: sem_tsem//造了一类资源
- 信号量的初始化: sem_init
- 信号量的PV操作: (核心)sem_wait()/sem_post()
- 信号量的销毁: sem_destroy
semaphore
信号量的定义:
semt:信号量的类型
sem:信号量的变量
- sem_t sem_w;
- sem_t sem_r;
sem_init --> int sem_init(semt_*semint psharedunsigned int value); 信号量的初始化:
功能:将已经定义好的信号量赋值。
参数:sem要初始化的信号量
- pshared = 0(!= 0); 表示线程间使用信号量(表示进程间使用信号量)
- value 信号量的初始值,一般无名信号量,都是二进制信号量,0,1
- 0 红灯,进程暂停阻塞
- 1 绿灯,进程可以通过执行
返回值:成功 0 失败 -1
//写资源
sem_w
sem_init(&sem_w,0,1)://1表示我有一个写资源可用
sem_t sem_r;
sem_init (&sem_r, 0, 0);
信号量的PV操作
- P==>申请资源=-=》申请一个二值信号量
- P操作对应函数=sem_wait0;
- V操作对应函数==sem_post0;
sem_wait --> int sem_wait(sem_t *sem); //p操作
功能:判断当前sem信号量是否有资源可用。
- 如果sem有资源(--1),则申请该资源,程序继续运行
- 如果sem没有资源(--0),则线程阻塞等待,一旦有资源则自动申请资源并继续运行程序。
注意:sen申请资源后会自动执行让资源数量-1;
参数:sem要判断的信号量资源
返回值:成功0 失败-1
sem_post --> intsem_post(sem_t *sem);//v操作
功能:函数可以将指定的sem信号量资源释放,并默认执行,让资源数量加1;线程在该函数上不会随塞。
参数:sem要释放资源的信号量
返回值:成功0 失败-1
sem_destroy --> int sem_destroy(semt *sem);
功能:使用完毕将指定的信号量销毁
参数:sem要销毁的信号量
返回值:成功0 失败-1
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <semaphore.h>
//创建信号量
sem_t sem_w;
sem_t sem_r;
char buf[1024];
//线程执行函数 ---- 线程要做的事情
void* do_sth1 (void *arg)
{
while (1)
{
sem_wait(&sem_w);
fgets(buf,sizeof(buf),stdin);
sem_post(&sem_r);
}
return NULL;
}
void* do_sth2(void *arg)
{
while (1)
{
sem_wait(&sem_r);
printf("buf = %s \n",buf);
sem_post(&sem_w);
}
return NULL;
}
int main(int argc, const char *argv[])
{
//信号量初始化
sem_init(&sem_w,0,1);
sem_init(&sem_r,0,0);
pthread_t tid[2];
int ret = pthread_create(&tid[0],NULL,do_sth1,NULL);
if (ret != 0)
{
errno = ret; //errno --系统的一个全局变量 用来存放 全局的错误码
perror("pthread_create fail");
return -1;
}
ret = pthread_create(&tid[1],NULL,do_sth2,NULL);
if (ret != 0)
{
errno = ret; //errno --系统的一个全局变量 用来存放 全局的错误码
perror("pthread_create fail");
return -1;
}
printf("main ----\n ");
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
return 0;
}
更多推荐



所有评论(0)