linux 线程创建 同步 资源回收

32 篇文章 0 订阅

例子1:互斥锁 + 条件变量

/*

主线程:创建两个线程,创建完了等待两个线程同步,并等待他们退出
线程1: 1)打印 XXX 2) 如果主程序进入等待状态叫醒他 3) 退出的时候自己回收资源
线程2: 1)打印 XXX 2) 如果主程序进入等待状态叫醒他 3)等待线程1 退出后

*/

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<errno.h>
#include<unistd.h>
#include <string.h>

#include<signal.h>

#define PRINT_ERROR(ret) do{ printf("ERROR: %s: %s\n",__FUNCTION__, strerror(ret)); }while(0);
#define PRINT_ERRORID(ret) do{ printf("%s: %d\n",__FUNCTION__, ret); }while(0);

int g_status=0; // 0: init 1:start wait 
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void* thread_1_fun(void*);
void* thread_2_fun(void*);

int main(int argc, char** argv)
{
	printf("main: start... \n");
	pthread_t thread_1, thread_2;
	int ret;

	printf("main: creete thread 1... \n");
	ret = pthread_create(&thread_1, NULL, thread_1_fun, NULL);
	if(ret != 0) PRINT_ERROR(ret);
	printf("main: creeate thread 1 end... \n");

	printf("main: create thread 2... \n");
	ret = pthread_create(&thread_2, NULL, thread_2_fun, &thread_1); // transfer thread 1 id as paramter
	if(ret != 0) PRINT_ERROR(ret);
	printf("main: creeate thread 2 end... \n");

	//这个等待有可能被 线程1 或者 线程2 唤醒 
	// 由于线程执行的不可预测性,唤醒前有可能收到两个线程发过来的 pthread_cond_signal,但是只有一个起作用
	pthread_mutex_lock(&mutex);
	printf("main: status 0->1 wait... \n");
	g_status = 1;
	pthread_cond_wait(&cond, &mutex);
	pthread_mutex_unlock(&mutex);

#if 0 //can set status to 2 and let thread 2 to wait and wakeup it
	pthread_mutex_lock(&mutex);
	printf("main: status 1->2 wait... \n");
	g_status = 2;
	pthread_cond_wait(&cond, &mutex);
	pthread_mutex_unlock(&mutex);
#endif

	//pthread_detach(thread_1);//也可以在子程序中 pthread_detach(pthread_self());
	ret = pthread_join(thread_1, NULL); //如果这个线程已经结束,返回错误:Invalid argument /如果是一个detach线程,返回错误:No such process
	if(ret != 0) PRINT_ERROR(ret);

	ret = pthread_join(thread_2, NULL); //等待 进程2结束并回收其占用的资源,8K堆栈
	if(ret != 0) PRINT_ERROR(ret);

	printf("main: end... \n");
	exit(0);
}

void* thread_1_fun(void* arg)
{
	printf("  T1: start... \n");
	
	//同步操作,等待主程序创建完线程 并 进入 等待状态
	while(1)
	{
		pthread_mutex_lock(&mutex);
		if(g_status == 1)
		{
			pthread_mutex_unlock(&mutex);
			break;
		}
		pthread_mutex_unlock(&mutex);
	}
	
	pthread_mutex_lock(&mutex);
	if(g_status == 1)
	{
		printf("  T1: wakeup main cond signal -> ...\n");
		pthread_cond_signal(&cond);
	}
	pthread_mutex_unlock(&mutex);

	printf("  T1: end \n");

	// 与主线程分离,线程结束的时候自己释放资源
	pthread_detach(pthread_self());
	//sleep(1);
	/*
		//也可以在创建的时候指定这个属性
		pthread_attr_t attr;
		pthread_t thread;
		pthread_attr_init (&attr);pthread_attr_setdetachstat(&attr, PTHREAD_CREATE_DETACHED);
		pthread_create (&thread, &attr, &thread_function, NULL);
	*/

	pthread_exit(0);
}

void* thread_2_fun(void* arg)
{
	printf("  T2: start... \n");

	//同步操作,等待主程序创建完线程 并 进入 等待状态
	while(1)
	{
		pthread_mutex_lock(&mutex);
		if(g_status == 1) //
		{
			pthread_mutex_unlock(&mutex);
			break;
		}
		pthread_mutex_unlock(&mutex);
	}

	pthread_mutex_lock(&mutex);
	if(g_status == 1)
	{
		printf("  T2: wakeup main cond signal -> ...\n");
		pthread_cond_signal(&cond);
	}
	pthread_mutex_unlock(&mutex);

	//等待线程1结束
	pthread_join(*(pthread_t*)arg, NULL);
	
	printf("  T2: end \n");
	pthread_exit(0);
}


例子二:信号量

/*

主线程:创建两个线程,创建完了等待两个线程同步,并等待他们退出
线程1: 1)打印 XXX 2) 如果主程序进入等待状态叫醒他 3) 退出的时候自己回收资源
线程2: 1)打印 XXX 2) 如果主程序进入等待状态叫醒他 3)等待线程1 退出后

*/

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<errno.h>
#include<unistd.h>
#include <string.h>

#include<signal.h>
#include <semaphore.h>

#define PRINT_ERROR(ret) do{ printf("ERROR: %s: %s\n",__FUNCTION__, strerror(ret)); }while(0);

sem_t sem1; //子线程等待主线程同步信号
sem_t sem2; //主线程等待子线程同步信号

void* thread_1_fun(void*);
void* thread_2_fun(void*);

int main(int argc, char** argv)
{
	printf("main: start... \n");
	pthread_t thread_1, thread_2;
	int ret;

	sem_init(&sem1,0,0);
	sem_init(&sem2,0,0);

	printf("main: create thread 1... \n");
	ret = pthread_create(&thread_1, NULL, thread_1_fun, NULL);
	if(ret != 0) PRINT_ERROR(ret);
	printf("main: create thread 1 end... \n");

	printf("main: creeate thread 2... \n");
	ret = pthread_create(&thread_2, NULL, thread_2_fun, &thread_1); // transfer thread 1 id as paramter
	if(ret != 0) PRINT_ERROR(ret);
	printf("main: creeate thread 2 end... \n");

	//同步信号开始
	printf("main: send first sync signal to child \n");
	sem_post(&sem1);
	printf("main: send second sync signal to child \n");
	sem_post(&sem1);

	// 阻塞并等待被唤醒(确认子线程是否都收到信号)
	printf("main: wait sync signal from child thread... \n");
	sem_wait(&sem2);
	printf("main: receive first sync signal from thread \n");
	sem_wait(&sem2);
	printf("main: receive second sync signal from thread \n");

	//sleep(1);
	//如果不等子线程 主线程执行完了之后,子线程也会被系统回收,并结束运行
	ret = pthread_join(thread_1, NULL); //如果这个线程已经结束,返回错误:Invalid argument /如果是一个detach线程,返回错误:No such process
	if(ret != 0) PRINT_ERROR(ret);

	ret = pthread_join(thread_2, NULL); //等待 进程2结束并回收其占用的资源,8K堆栈
	if(ret != 0) PRINT_ERROR(ret);

	printf("main: end... \n");
	exit(0);
}

void* thread_1_fun(void* arg)
{
	printf("  T1: start & wait for sync... \n");
	sem_wait(&sem1);
	printf("  T1: sync OK \n");

	printf("  T1: send sync signal to main \n");
	sem_post(&sem2);

	while(1)
	{
		printf("  T1: running.. \n");
		sleep(1);
	}

	printf("  T1: end \n");

	pthread_exit(0);
}

void* thread_2_fun(void* arg)
{
	printf("  T2: start & wait for sync... \n");
	sem_wait(&sem1);
	printf("  T2: sync OK \n");

	printf("  T2: send sync signal to main \n");
	sem_post(&sem2);

	while(1)
	{
		printf("  T2: running.. \n");
		sleep(1);
	}

	printf("  T2: end \n");

	pthread_exit(0);
}

如下内容来源 https://blog.csdn.net/u013139008/article/details/78584724

创建线程时的属性设置
1. 线程的调度策略:
SCHED_OTHREAD 非实时调度策略。线程优先级为0,每个线程都不抢占其他的线程。线程会受到时间片的限制。会一直占用系统分配给他的时间片。
SCHED_RR 实时调度策略。线程优先级1-99,数值越大,优先级越高。系统分配给一个线程一个时间片,这个时间片运行过程中不会被打断。但是当时间片运行结束,下一个时间片会分给优先级更高的线程。
SCHED_FIFO 实时调度策略。线程优先级1-99,数值越大,优先级越高。时间片首先分配给优先级最高的线程。一旦时间片分配给一个线程,除非线程主动挂起和退出,该线程会一直占用CPU。线程按照不同的优先级有不同的线程队列。在一个队列中先进先出。
=>实时调度策略会抢占非实时调度策略。除非非实时的线程运行结束,否则实时的线程是不可能得到运行的。
  一个进程里面可能有多种调度策略的线程。
pthread_attr_t attr;
struct sched_param param;
param._sched_prority = 10;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_RR/SCHED_FIFO);
pthread_attr_setschedparam(&attr, &param);
pthread_create(xxx, &attr, xxx, xxx);
pthread_attr_destroy(&attr);


2. 线程优先级的作用范围:
PTHREAD_SCOPE_SYSTEM 线程的优先级的作用范围是整个系统。即线程和系统中所有的线程竞争CPU的时间。
PTHREAD_SCOPE_PROCESS 线程的优先级的作用氛围是当前进程。即线程和该进程中其他线程竞争CPU时间。
pthread_attr_t attr;
struct sched_param param;
param._sched_prority = 10;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_RR/SCHED_FIFO);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM/PTHREAD_SCOPE_PROCESS);
pthread_create(xxx, &attr, xxx, xxx);
pthread_destroy(&attr);


3. 线程和其他线程是否分家:
PTHREAD_CREATE_DETACHED 新线程不能用pthread_join函数来同步,而且在退出时自行释放所占用的资源。
PTHREAD_CREATGE_JOINABLE 默认值。可以使用pthread_detach(pthread_id)改变分家状态。
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);


4. 线程栈的大小:
栈是线程的属性,在创建线程的时候,可以指定栈的大小。但是程序运行的过程中,栈的大小不能改变。即线程创建出来,大小就确定。
int stack_size;
pthread_attr_setstacksize(&attr, stack_size);
pthread_attr_getstacksize(&attr, &stack_size);
PTHREAD_STACK_MIN 栈的最小值
 

...

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值