线程相关内容

1、线程的概述

◼ 与进程(process)类似,线程(thread)是允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程。
同一个程序中的所有线程均会独立执行相同程序,且共享同一份全局内存区域,其中包括初始化数据段、未初始化数据段,以及堆内存段。(传统意义上的 UNIX 进程只是多线程程序的一个特例,该进程只包含一个线程)
◼ 进程是 CPU 分配资源的最小单位,线程是操作系统调度执行的最小单位。
◼ 线程是轻量级的进程(LWP:Light Weight Process),在 Linux 环境下线程的本质仍是进程。
◼ 查看指定进程的 LWP 号:ps –Lf pid

2、线程和进程区别

◼ 进程间的信息难以共享。由于除去只读代码段外,父子进程并未共享内存,因此必须采用一些进程间通信方式,在进程间进行信息交换。
◼ 调用 fork() 来创建进程的代价相对较高,即便利用写时复制技术,仍然需要复制诸如内存页表和文件描述符表之类的多种进程属性,这意味着 fork() 调用在时间上的开销依然不菲。
◼ 线程之间能够方便、快速地共享信息。只需将数据复制到共享(全局或堆)变量中即可。
◼ 创建线程比创建进程通常要快 10 倍甚至更多。线程间是共享虚拟地址空间的,无需采用写时复制来复制内存,也无需复制页表

3、线程之间共享和非共享资源

◼ 共享资源
 进程 ID 和父进程 ID
 进程组 ID 和会话 ID
 用户 ID 和 用户组 ID
 文件描述符表
 信号处置
 文件系统的相关信息:文件权限掩码
(umask)、当前工作目录
 虚拟地址空间(除栈、.text)
◼ 非共享资源
 线程 ID
 信号掩码
 线程特有数据
 error 变量
 实时调度策略和优先级
 栈,本地变量和函数的调用链接信息

4、怎么去创建一个线程

/*
一般main函数所在线程为主线程,其余为子线程
程序默认只有一个进程,fork()函数调用,2执行
程序默认只有一个线程,pthread_create()函数调用,2个线程
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
    -功能:创建一个子进程
    -参数:
         -thread:传出参数,线程创建成功后,子线程的线程ID被写入该变量中
         -attr:设置线程的属性,NULL
         -start_routine:函数指针,子线程需要处理的逻辑代码
         -arg:传参
    -返回值:
         成功:0
         失败:错误号
         获取错误号信息: char *strerror(int errnum);

*/
#include<stdio.h>
#include<pthread.h>
#include<string.h>
void *callback(void * arg)
{
    printf("child thread....");
    return NULL;
}
int main()
{
    //创建一个子进程
    pthread_t tid;
    int ret=pthread_create(&tid,NULL,callback,NULL);
    if(ret!=0)
    {

    char *errstr=strerror(ret);
    printf("error: %s/n",errstr);
    }
   for(int i=0;i<5;i++)
   {
       printf("%d\n",i);
   }
  

    return 0; //exit(0);
}

5.终止进程

 /*#include <pthread.h>
  void pthread_exit(void *retval); 
  功能:终止一个线程,在哪个线程中调用,就表示终止哪个线程
  参数:
     retval:需要传递一个指针,作为一个返回值,返回给pthread_join()
 int pthread_equal(pthread_t t1, pthread_t t2);
    功能:比较两个线程ID是否相等
    不同的操作系统,pthread_t 类型的实现不一样
  */
#include<stdio.h>
#include<pthread.h>
#include<string.h>
void *callback(void *arg)
{
    printf("child thread id:%ld\n",pthread_self());
    return NULL;
}
int main()
{
    //创建一个子线程
    pthread_t tid;
   int ret= pthread_create(&tid,NULL,callback,NULL);
   if(ret!=0)
   {
       char * errstr=strerror(ret);
       printf("error:%s\n",errstr);
   }
    //主线程
    for(int i=0;i<5;i++)
    {
        printf("%d\n",i);
    }

   printf("tid:%ld,man thread id:%ld\n",tid,pthread_self());
   //让主线程退出,不会影响其他正常运行的线程
   pthread_exit(NULL);
    return 0;
}

6.回收子线程资源

/*
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
    -功能:和一个已经终止的线程进行连接
           回收子线程的资源
           这个函数是阻塞函数,调用一次回收一个子线程
           一般在主线程中使用
    -参数:
        -thread:需要回收的子线程的ID
        -retval:接受子进程退出的返回值
    -返回值:
        0:成功
        非0:错误号

*/
#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<unistd.h>
int value=10;//定义一个全局变量
void *callback(void *arg)
{
    printf("child thread id:%ld\n",pthread_self());
    sleep(3);
    //int value=10; //局部变量  不要从局部变量获取

    pthread_exit((void *)&value);
}
int main()
{
    //1.创建一个子线程
    pthread_t tid;
   int ret= pthread_create(&tid,NULL,callback,NULL);

   if(ret!=0)
   {
       char * errstr=strerror(ret);
       printf("error:%s\n",errstr);
   }

    //2. 主线程
    for(int i=0;i<5;i++)
    {
        printf("%d\n",i);
    }

   printf("tid:%ld,man thread id:%ld\n",tid,pthread_self());


   //3. 主线程调用pthread_join()回收子线程资源
   int * thread_retval;
   ret=pthread_join(tid,(void **)&thread_retval);
   if(ret!=0)
   {
       char * errstr=strerror(ret);
       printf("error:%s\n",errstr);
   }
   printf("exit data:%d\n",*thread_retval);
   printf("回收子线程资源成功\n");

   //4.让主线程退出,不会影响其他正常运行的线程
   pthread_exit(NULL);
    return 0;
}

7.分离一个线程

int pthread_detach(pthread_t thread);
/*
#include <pthread.h>
int pthread_detach(pthread_t thread);
功能:分离一个线程,被分离的线程在终止时,会释放资源给系统
1.不能多次分离
2.不能连接一个已经分离的线程
参数:需要分离的线程的ID
成功:0
失败:错误号

*/
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<pthread.h>
void * callback(void *arg)
{
printf(“child thread: %ld\n”,pthread_self());
return NULL;
}
int main()
{
//1.创建一个子线程
pthread_t tid;
int ret=pthread_create(&tid,NULL,callback,NULL);
if(ret!=0)
{
char *errstr=strerror(ret); //定义一个字符串接收错误
printf(“error: %s\n”,errstr);
}
//2.输出主线程和子线程的ID
printf(“tid: %ld, main thread id: %ld\n”,tid,pthread_self());
//3.设置子线程分离,子线程结束时对应的资源不需要主线程释放
pthread_detach(tid);

pthread_exit(NULL);
return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值