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 ();
信号量的分类:

  • 信号无名量  ==》线程间通信
  • 有名信号量 ==》 进程间的通信

框架

  1. 信号量的定义:        sem_tsem//造了一类资源
  2. 信号量的初始化:        sem_init
  3. 信号量的PV操作:        (核心)sem_wait()/sem_post()
  4. 信号量的销毁:    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;
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐