多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序。一般情况下,两种类型的多任务处理:基于进程和基于线程

  • 基于进程的多任务处理是程序的并发执行。
  • 基于线程的多任务处理是同一程序的片段的并发执行。

1. POSIX

POSIX Threads 或 Pthreads 提供的 API 可在多种类 Unix POSIX 系统上可用,比如 FreeBSD、NetBSD、GNU/Linux、Mac OS X 和 Solaris。

  • 创建线程

    1
    2
    3
    4
    #include "pthread.h"

    // 函数原型
    int pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg);

    pthread_create创建一个新的线程,并让它可执行。

    • 返回值:成功创建为0;

    • 参数:

      • th:指向线程标识符的指针;
      • attr:用于设置线程属性,可以使用默认值NULL;
      • func:线程运行函数起始地址,一旦线程被创建就会执行;
      • arg:运行函数的参数,它必须通过把引用作为指针强制转换为 void 类型进行传递。如果没有传递参数,则使用 NULL。
  • 终止线程

    如果需要只终止某个线程而不终止整个进程,可以有三种方法:

    1. 从线程函数return。这种方法对主线程不适用,从main函数return相当于调用 exit 。
    2. 一个线程可以调用pthread_cancel终止同一进程中的另一个线程。
    3. 线程可以调用pthread_exit终止自己。

    使用下面的程序,我们可以用它来终止一个 POSIX 线程:

    1
    2
    // 函数原型
    void pthread_exit(void *res);

    resvoid *类型,和线程函数返回值的用法一样,其它线程可以调用pthread_join获得这个指针。

    1
    int pthread_join(pthread_t t, void **res);

    调用该函数的线程将挂起等待,直到id为t的线程终止。t线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:

    1. 如果t线程通过return返回, res所指向的单元里存放的是 t线程函数的返回值。
    2. 如果t线程被别的线程调用pthread_cancel异常终止掉, res 所指向的单元里存放的是常数PTHREAD_CANCELED
    3. 如果t线程是自己调用pthread_exit终止的,res所指向的单元存放的是传给pthread_exit的参数。
  • 创建与退出线程示例

    • 代码示例1

      输出:

      1
      2
      main thread: pid 26709 tid 3731060480 (0xde637700)
      new thread: pid 26709 tid 3722659584 (0xdde34700)
    • 代码示例2

      输出:

      1
      2
      3
      4
      5
      6
      7
      8
      thread 1 returning
      thread 1 exit code 1
      thread 2 exiting
      thread 2 exit code 2
      thread 3 writing
      thread 3 writing
      thread 3 writing
      thread 3 exit code -1
  • 向线程传递参数

    向线程传递参数时,涉及数据类型转化,记得进行转化。

  • 线程同步

    线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点。linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量和信号量。

    代码示例

    • 互斥锁(mutex)

      通过锁机制实现线程间的同步。同一时刻只允许一个线程执行一个关键部分的代码。

      互斥锁是通过锁的机制来实现线程间的同步问题。互斥锁的基本流程为:

      • 定义,初始化一个互斥锁

        1
        2
        pthread_mutex_t mutex;	//声明
        int a = pthread_mutex_init(&counter_mutex, NULL); //初始化
      • 加锁:pthread_mutex_lock()函数或

      • pthread_mutex_trylock()函数

      • 对共享资源的操作

      • 解锁:pthread_mutex_unlock()函数

      • 注销互斥锁:pthread_mutex_destory()函数

    • 条件变量(condition Variable)

      • 定义、初始化

        1
        2
        pthread_cond_t cond;
        int res = pthread_cond_init(&cond, NULL);
      • 等待条件变量

        1
        int res = pthread_cond_wait(&cond, &mutex);

        参数说明:cond 条件变量地址,mutex互斥锁地址,表示锁等待在条件变量上.

      • 唤醒等待条件变量上的线程

        1
        2
        int pthread_cond_signal(pthread_cond_t *cond);               //唤醒等待该条件变量上的某个线程
        int pthread_cond_broadcast(pthread_cond_t *cond); //唤醒等待该条件变量上的所有线程
      • 销毁条件变量:

        1
        int pthread_cond_destroy(pthread_cond_t *cond);
    • 信号量(Semaphore)

      这里先不介绍….

  • 未完待续