线程的定义(以下摘自维基)

线程是操作系统能够进行运算调度的最小单位。包含在进程中,是进程中实际的运作单位。一个线程指的是进程中一个单一顺序的控制流,一个进程可以并发多个线程,每个线程并行执行不同的任务。(在一些类Unix的系统中也被称为轻量进程,但是轻量进程更多指的是内核线程,而用户线程称为线程)
线程是独立调度和分配的基本单位。
同一进程中的多条线程将共享进程中的全部系统资源。例如虚拟地址空间,文件描述符和信号处理等等,因为线程没有自己单独的地址空间(共享进程的地址空间),当一个线程死掉就等于整个进程死掉。但是每个线程都有各自的调用栈(call stack)、寄存器地址(register context)和本地存储(thread-local storage)。
在多核或多CPU,或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见,即提高了程序的执行吞吐率。在单CPU单核的计算机上,使用多线程技术,也可以把进程中负责I/O处理、人机交互而常被阻塞的部分与密集计算的部分分开来执行,编写专门的workhorse线程执行密集计算,从而提高了程序的执行效率。

POSIX线程有关API

int pthread_create(pthread_t * thread ,const pthread_attr_t *attr, void *(*start_routine)(void *),void *arg); 
// 线程创建
int pthread_join(pthread_t thread, void **retval);
//线程等待
void pthread_exit(void* retval);
//线程终止运行

以下源码引用自IBM Develop,
Daniel Robbins 大佬的博客,侵权删

# include <pthread.h>
# include <stdlib.h>
# include <unistd.h>
void *thread_function(void *arg) {
  int i;
  for ( i=0; i<20; i++) {
    printf("Thread says hi!\n");
    sleep(1);
  }
  return NULL;
}
int main(void) {
  pthread_t mythread;
   
  if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {
    printf("error creating thread.");
    abort();
  }
  if ( pthread_join ( mythread, NULL ) ) {
    printf("error joining thread.");
    abort();
  }
  exit(0);
}

要编译这个程序,只需先将程序存为 thread1.c,然后输入:

$ gcc thread1.c -o thread1 -lpthread //-l 参数为调用外部动态链接库pthread

理解thread1.c
pthread_create函数中

  • 第一个参数 &mythread是类型为pthread_t类型的变量,相当于线程句柄,为创建后的线程分配一个tid
  • 第二个参数NULL,表示为线程的某些属性(具体内容不知道),一般为缺省属性(NULL)
  • 第三个参数是线程所分配到的函数,也就是线程启动时调用的函数。
  • 第四个参数NULL是向线程传递参数,可以使用void *通用指针的数据类型。这样可传入参数的就变得很多了。
  1. 这里的判断可以有效的避免创建线程失败后发生未知的现象,这一点在国外的开发者种极为常见,在国内的blog大多数的代码内容都没有这么严谨,考虑错误情况。
    在线程创建完毕后,当前程序总共存在有两个线程,一个是主线程,一个是新创建的线程,两者没有进程中的父子关系,是同等级别的关系,
  2. 线程是并发运行的。即使在单处理器系统上运行(内核利用时间分片模拟多任务) 也是可以的
    接下来调用pthread_join(mythread,NULL) ,这个函数在网上的作用大部分都是说用来让pthread_join所在的线程先挂起,等待第一个参数中的线程执行完毕。然而实际的使用中发现,调用这个函数之后,主线程并没有停止!后来在IBM Develop中看到对这个函数的解释———合并资源。我觉得这才是pthread_join的真正作用。让第一个参数中的线程执行完毕并且将其所占有的资源与主线程合并(和pthread_join所在线程合并)。之所以需要这个操作,是因为线程创建到结束,通过不主动将其释放资源(利用pthread_exti或者pthread)_join),其始终会占据着系统的资源不会自己主动释放。

    实际案例:

    创建一个包含所有已停止线程的全局“死线程列表”,然后让一个专门的清理线程专等停止的线程加到列表中。这个清理线程调用 pthread_join() 将刚停止的线程与自己合并。现在,仅用一个线程就巧妙和有效地处理了全部清理。
    最后程序结束。