Linux线程创建,退出,等待

目录​​​​​​​

一 为什么使用线程

1.1概念

1.2使用线程的理由

二 线程的创建,退出,等待 

2.1 线程创建

2.2 线程退出

2.3.线程等待

2.4. 线程ID获取及比较


一 为什么使用线程

1.1概念

概念:"进程——资源分配的最小单位,线程——程序执行的最小单位"。线程是进程内部的一条执行序列或执行路径,一个进程可以包含多条线程。线程是进行资源调度和分配的基本单位 。

一个进程在同一时刻只做一件事情。有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务。  

Linux线程创建,退出,等待_第1张图片 单线程和多线程图
  •         进程是程序执行时的一个实例,是担当分配系统资源(CPU时间、内存等)的基本单位。在面向线程设计的系统中,进程本身不是基本运行单位,而是线程的容器。程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。
    •         线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。线程包含了表示进程内执行环境必须的信息,其中包括进程中表示线程的线程ID、一组寄存器值、栈、调度优先级和策略、信号屏蔽字、errno常量以及线程私有数据。进程的所有信息对该进程的所有线程都是共享的,包括可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。
      •         在Unix和类Unix操作系统中线程也被称为轻量级进程(lightweight processes),但轻量级进程更多指的是内核线程(kernel thread),而把用户线程(user thread)称为线程。

1.2使用线程的理由

多线程程序作为一种多任务、并发的工作方式,当然有以下的优点:

  1. 提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time consuming)置于一个新的线程,可以避免这种尴尬的情况。
  2. 使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
  3. 改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。

二 线程的创建,退出,等待 

2.1 线程创建

函数原型:pthread_create()

#include 
// 返回:若成功返回0,否则返回错误编号
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                                      void *(*start_rtn)(void *), void *restrict arg);

首先,使用该函数需要包含头文件。

函数参数及返回值如下所示:

  •  thread:   由tidp指向的内存单元被设置为新创建线程的线程ID
  • attr:   attr用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程。
  • start_rtn():   新创建的线程从start_rtn函数的地址开始运行,
  • argv:   该函数只有一个无类型指针参数arg。如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。
  • 返回值:若成功返回0,否则返回错误编号

pthread_create成功返回时,由tidp指向的内存单元被设置为新创建线程的线程ID。

#include 
#include 
#include 

void fun1()
{
    while(1)
    {
        puts("线程");
        sleep(1);
    }
}

 void main()
 {
    pthread_t t1;
    pthread_create(&t1,NULL,(void *)fun1,NULL);
    while(1)
    {
        puts("主线程");
        sleep(1);
    }
 }

 运行结果,主线程和创建的新线程每秒打印一次字符串Linux线程创建,退出,等待_第2张图片

2.2 线程退出

单个线程可以通过以下三种方式退出,在不终止整个进程的情况下停止它的控制流:

  1. 线程只是从启动例程中返回,返回值是线程的退出码。
  2. 线程可以被同一进程中的其他线程取消。
  3. 线程调用pthread_exit:
#include 

int pthread_exit(void *rval_ptr);

 首先,使用该函数需要包含头文件。

函数参数及返回值如下所示:

retval 是 void* 类型的指针,可以指向任何类型的数据,它指向的数据将作为线程退出时的返回值。如果线程不需要返回任何数据,将 retval 参数置为 NULL 即可。

retval是返回信息,”临终遗言“,可以给可以不给

该变量不能使用临时变量。

可使用:全局变量、堆上开辟的空间、字符串常量

2.3.线程等待

#include 

int pthread_join(pthread_t thread, void **rval_ptr);// 返回:若成功返回0,否则返回错误编号

函数参数及返回值如下所示:

  •  thread:  要等待的线程标识符
  • retval:   接收返回值:若是return退出的,接收入口函数的返回值,pthread_exit退出的,接收该函数的参数
#include 
#include 
#include 

void fun1()
{
    while(1)
    {
        puts("线程");
        sleep(1);
        pthread_exit(NULL);
    }
}

 void main()
 {
    pthread_t t1;
    pthread_create(&t1,NULL,(void *)fun1,NULL);
    pthread_join(&t1,NULL);
 }

 调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。如果例程只是从它的启动例程返回,rval_ptr将包含返回码。

如果对线程的返回值不感兴趣,可以把rval_ptr置为NULL。在这种情况下,调用pthread_join函数将等待指定的线程终止,但并不获得线程的终止状态。

2.4. 线程ID获取及比较

线程ID获取 pthread_self()

#include 

pthread_t pthread_self(void);// 返回:调用线程的ID

对于线程ID比较,为了可移植操作,我们不能简单地把线程ID当作整数来处理,因为不同系统对线程ID的定义可能不一样。我们应该要用下边的函数:

#include 

int pthread_equal(pthread_t tid1, pthread_t tid2);

// 返回:若相等则返回非0值,否则返回0

 返回值:若相等则返回非0值,否则返回0Linux线程创建,退出,等待_第3张图片

你可能感兴趣的:(Linux,C应用编程(概念类),开发语言,linux,c语言)