线程回收 day34

十四:system

int system(const char *command); 		//fork+exec     cd  /home
//命令行怎么写,它括号里就怎么写
//执行不了cd,因为fork,在子进程执行不影响父进程

功能:使用该函数可以将shell命令直接在代码中执行。
参数:command要执行的shell命令
返回值:成功 0 ,失败 -1

六:线程

一:基础定义

优点: 比多进程节省资源,可以共享变量。

概念:线程是轻量级进程,一般是一个进程中的多个任务。

进程是系统中最小的资源分配单位.

线程是系统中最小的执行单位

都能并发完成任务,

特征:1、共享资源
2、效率高 30%
3、三方库: pthread clone posix
3.1 编写代码头文件: pthread.h
3.2 编译代码加载库: -lpthread library
libpthread.so
gcc 1.c -lpthread
缺点:1,线程和进程相比,稳定性,稍微差些
2,线程的调试gdb,相对麻烦些。
info thread
*1
2
3
thread 3

二:与进程区别

1.线程属于某个进程

2.当进程运行起来后,默认有一个线程。主线程

3.线程与线程,平级。没有主次之分

4.创建的开销不同。进程3G。线程8M栈区独立

5.线程空间是共享的(除了栈区)。进程空间独立。

6.稳定性。线程弱,进程强。(线程一崩全崩)

资源:
线程比进程多了共享资源。 IPC
线程又具有部分私有资源。
进程间只有私有资源没有共享资源。
空间:
进程空间独立,不能直接通信。
线程可以共享空间,可以直接通信。

三:框架和函数s

线程的设计框架 posix:创建多线程 -->线程空间操作 -->线程资源回收

一:创建多线程pthread_create/pthread_self
int pthread_create(
		pthread_t *thread, const pthread_attr_t *attr,
		void *(*start_routine) (void *), void *arg);
---------------------------------------------------------------------------------
pthread_t pthread_self(void);	//获得当前线程的tid号
功能:该函数可以创建指定的一个线程。
参数:thread 线程id,需要实现定义并由该函数返回。
	  attr   线程属性,一般是NULL,表示默认属性。
	  start_routine 指向指针函数的函数指针。
	  		本质上是一个函数的名称即可。称为th
	  		回调函数,是线程的执行空间。
	  arg  回调函数的参数,即参数3的指针函数参数。
返回值:成功 0
	   失败 错误码
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void *th1(void *arg)
{
    while(1)
    {
        printf("send vedio  tid:%lu\n",pthread_self());
        sleep(1);
    }
    return NULL;
}

void *th2(void *arg)
{
    while(1)
    {
        printf("receve ctrl tid:%lu\n",pthread_self());
        sleep(1);
    }
    return NULL;
}

int	main(int argc, char **argv)//主线程运行main函数
{
    pthread_t tid1,tid2;
    pthread_create(&tid1, NULL, th1, NULL);//线程2
    pthread_create(&tid2, NULL, th2, NULL);//线程3

    while(1)
    {
      	sleep(1);//进程结束的一个条件是主线程走完程序结束,所以让他不要结束	
        printf("main tid:%lu \n",pthread_self());
    }

    //system("pause");
    return 0;
}

二:线程的退出

自行退出 -->自杀 -->子线程自己退出

void pthread_exit(void *retval);  exit  return p;
//想要函数带回的话,直接用这个也行,不带回,参数写NULL即可

功能:子线程自行退出
参数: retval 线程退出时候的返回状态,临死遗言。
返回值:无

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void* th(void* arg)
{
    int i = 5;
    while(i--)
    {
        printf("th :%lu\n",pthread_self());
        sleep(1);
    }
    pthread_exit(NULL);//自己调用自己,自己杀自己
}

int	main(int argc, char **argv)
{
    pthread_t tid;
    pthread_create(&tid, NULL, th, NULL);

    while (1)sleep(1);

    //system("pause");
    return 0;
}

强制退出 ==》他杀 ==》主线程结束子线程

int pthread_cancel(pthread_t thread);

功能:请求结束一个线程
参数:thread 请求结束一个线程tid
返回值:成功 0
失败 -1;

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>


void* th(void*arg)
{
    
    while(1)
    {
        printf("th is %lu\n",pthread_self());
        sleep(1);
    }

    pthread_exit(NULL);
    //return NULL; 从功能角度描述,两者一致。建议调用pthread_exit();
}

int	main(int argc, char **argv)
{
    
    pthread_t tid;
    pthread_create(&tid,NULL,th,NULL);
    int i = 0 ;
    while(1)
    {
        printf("main tid:%lu, i:%d\n",pthread_self(),i);
        sleep(1);
        i++;
        if(5 == i )
        {
            pthread_cancel(tid);//主函数调用,他杀,本质上都是子进程死亡
        }
    }

    //system("pause");
    return 0;
}
三:线程回收

线程的回收机制 ====》不同与进程没有孤儿线程和僵尸线程。
====》主线程结束任意生成的子线程都会结束。
====》子线程的结束不会影响主线程的运行。

int pthread_join(pthread_t thread, void **retval);

功能:通过该函数可以将指定的线程资源回收,该函数具有
阻塞等待功能,如果指定的线程没有结束,则回收线程
会阻塞。
参数:thread 要回收的子线程tid
retval 要回收的子线程返回值/状态。==》ptread_exit(值);
返回值:成功 0, 失败 -1;

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void* th(void* arg)
{
  int i = 5;
  while (i--)
  {
    printf("th is %lu\n", pthread_self());
    sleep(1);
  }

  pthread_exit(NULL);
  // return NULL; 从功能角度描述,两者一致。建议调用pthread_exit();
}

int main(int argc, char** argv)
{
  pthread_t tid;
  pthread_create(&tid, NULL, th, NULL);

  pthread_join(tid, NULL);//同步 //阻塞回收。 如果th没有结束,会一直等待。如果结束,才能回收
  printf("th is end\n");
  // while(1)sleep(1);

  // system("pause");
  return 0;
}
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void* th(void* arg)
{
  static char buf[] = "我要消亡";//在data区,没有static,生命周期短,无法正确返回buf
  // char* buf =malloc(15);
  pthread_exit(buf);
  // return NULL; 从功能角度描述,两者一致。建议调用pthread_exit();
}

int main(int argc, char** argv)
{
  pthread_t tid;
  pthread_create(&tid, NULL, th, NULL);

 //这个就当规范写法
  void* ret = NULL;//空指针,万能指针接受
  pthread_join(tid, &ret);  // void**  改变指针的指向
  printf("th is end,ret %s\n", (char*)ret);

  return 0;
}

子线程的回收策略:
1、如果预估子线程可以有限范围内结束则正常用pthread_join等待回收。
2、如果预估子线程可能休眠或者阻塞则等待一定时间后强制回收。
3、如果子线程已知必须长时间运行则,不再回收其资源。

四:线程传参
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void *th(void *arg) {
  char *tmp = (char *)arg;//让他类型一致
  strcat(arg, ",wolrd");

  return arg;
}

int	main(int argc, char **argv)
{
    char buf[1238] = "hello";

    pthread_t tid;
    pthread_create(&tid, NULL, th, buf);
    void* ret;
    pthread_join(tid, &ret);

    printf("buf:%s\n",(char*)ret);

    //system("pause");
    return 0;
}
//结构体传参
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

typedef struct {
  int id;
  char name[256];
} PER;

void *th(void *arg) {
  PER *tmp = (PER *)arg;
  printf("%d %s\n", tmp->id, tmp->name);
  return NULL;
}

int main(int argc, char **argv) {
  pthread_t tid;
  PER per;
  char buf[256] = {0};
  printf("input if to per\n");
  fgets(buf, sizeof(buf), stdin);
  per.id = atoi(buf);

  printf("input if to name\n");
  fgets(per.name, sizeof(per.name), stdin);
  per.name[strlen(per.name) - 1] = '\0';

  pthread_create(&tid, NULL, th, &per);
  pthread_join(tid, NULL);

  //system("pause");
  return 0;
}
int detachstate);

​ 功能:把一个线程设置成相应的属性
​ 参数,attr,属性变量,有init函数初始化他。
​ detachstate:有2个可选值,

PTHREAD_CREATE_DETACHED:设置分离属性。

int pthread_deatch(pthread_t thread);

​ 功能,设置分离属性
​ 参数,线程id号,填自己的id

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

void *th(void *arg)
{
  //方法2 。 设置分离属性 。当线程退出后,栈区由系统回收。
  pthread_detach(pthread_self());
  return NULL;
}
int main(int argc, char **argv)
{
  int i = 0;
  for (i = 0; i < 100000; i++)
  {
    pthread_t tid;
    int ret = pthread_create(&tid, NULL, th, NULL);//回收成功返回0
    if (ret != 0)
    {
      break;
    }
    // pthread_detach(tid); 方法1
  }

  printf("i is %d\n", i);
  // system("pause");
  return 0;
}
4.1通过函数回收(两个函数类似于do - while)
void pthread_cleanup_push(void (*routine)(void *)void *arg);
功能:注册一个线程清理函数
参数,routine,线程清理函数的入口
	arg,清理函数的参数。
返回值,无
void pthread_cleanup_pop(int execute);

​ 功能:调用清理函数
​ execute,非0 执行清理函数
​ 0 ,不执行清理
​ 返回值,无

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void clean(void *arg)
{
    printf("this is clean fun ,%s\n",(char*)arg);
    free(arg);

}
int	main(int argc, char **argv)
{
    
    char * p = malloc(50);
    

    pthread_cleanup_push(clean, p);

    strcpy(p,"hello");

    printf("main th in the ending...\n");
    //system("pause");
    pthread_cleanup_pop(1);
    return 0;
}
五:创建多子线程
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void *th1(void *arg) {
  printf("child tid1:%lu\n", pthread_self());
  return NULL;
}
void *th2(void *arg) {
  printf("child tid2:%lu\n", pthread_self());
  return NULL;
}
void *th3(void *arg) {
  printf("child tid3:%lu\n", pthread_self());
  return NULL;
}
void *th4(void *arg) {
  printf("child tid4:%lu\n", pthread_self());
  return NULL;
}
void *th5(void *arg) {
  printf("child tid4:%lu\n", pthread_self());
  return NULL;
}

int main(int argc, char **argv) {
  pthread_t tid[5];
  void *(*funcs[5])(void *) = {th1, th2, th3, th4, th5};
    //写成这种形式,函数指针类型,指向一个参数为 void*,返回值为 void* 

    //typedef void *(*ThreadFunc)(void *);
    //ThreadFunc funcs[5] = {th1, th2, th3, th4, th5};
    //typedef的写法
    
    
  for (int i = 0; i < 5; i++) {
    pthread_create(&tid[i], NULL, funcs[i], NULL);
  }

  while (1)
    sleep(1);

  // system("pause");
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值