跳至主要內容

线程(Thread)

西风逍遥游大约 3 分钟

线程(Thread)

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由 CPU 独立调度执行,在多 CPU 环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。

很多人把线程和进程放到一起做对比,然而实际上,线程和进程并不是处于同一层级下。线程是CPU调度的概念,表示的一条执行路径,CPU一个核执行函数,那么这就是一个线程。而进程是操作系统管理内存和执行单元的概念,表示的是一片独立的内存空间,一个进程可以包含多个线程,多个线程共享进程的内存空间。

线程的用途

线程的出现是为了解决多任务处理中的一些问题,比如说:

  • 如何在下载文件的同时,还能快速响应UI界面?
  • 如何利用多核资源,快速处理大量计算任务?
  • 如何同时处理多个网络请求,提高用户体验?

多任务处理时,分线程来处理不同的任务,可以提高程序的运行效率,同时也能提高用户体验。

线程的使用

我们这里主要介绍一下Linux下pthread线程库的使用。这是一个POSIX标准的线程库,被广泛应用于Linux, Unix, MacOS等系统中。

创建新线程

int pthread_create (pthread_t *thread,pthread_attr_t *attr,void *(*start_routine)(void *),void *arg);
  • thread 是线程标识符,但这个参数不是由用户指定的,而是由 pthread_create 函数在创建时将新的线程的标识符放到这个变量中。
  • attr 指定线程的属性,可以用 NULL 表示默认属性。
  • start_routine 指定线程开始运行的函数。
  • arg 是 start_routine 所需要的参数,是一个无类型指针。

若创建成功,返回0;若出错,则返回错误编号。

结束线程

当发生以下情形之一时,线程就会结束:

  • 线程运行的函数return了,也就是线程的任务已经完成;
  • 线程调用了 pthread_exit 函数;
  • 其他线程调用 pthread_cancel 结束这个线程;
  • 进程调用 exec() 或 exit(),结束了;
  • main() 函数先结束了,而且 main() 自己没有调用 pthread_exit 来等所有线程完成任务。

主线程一般会使用 pthread_join 函数来等待子线程结束,这样可以保证主线程在子线程结束之后再结束,否则主线程结束了,子线程也会被强制结束。

int pthread_join(pthread_t thread, void **retval);
  • thread 是线程标识符,指定要等待的线程。
  • retval 是一个无类型指针,线程结束时的返回值会赋给这个地址。

若成功,返回0;若出错,则返回错误编号。

用户线程可以调用 pthread_exit 函数来结束自己的线程,这个函数的作用和 return 一样,只是 return 是返回到调用者,而 pthread_exit 是直接结束线程。

void pthread_exit (void *retval);

retval 是由用户指定的参数, pthread_exit 完成之后可以通过这个参数获得线程的退出状态。

主线程也可以调用 pthread_cancel 函数来强制结束子线程,这个函数的作用是向子线程发送一个取消请求,子线程会在合适的时候结束。

int pthread_cancel (pthread_t thread);