Pthread 开发-入门

Pthread 开发-入门

在内存共享式的多处理器架构中,线程可用用于实现并行机制(parallelism)。然而由于历史原因,硬件供应商们的对线程的实现并不相同,使得开发者不得不考虑代码移植问题。对于UNIX系统,存在一套基于 IEEE POSIX 1003.1c 标准的标准 C 语言线程编程接口,这就是 Pthread。
Pthread 线程库主要分为三个主要部分:线程管理,互斥量,条件变量。共有约100个 API,它们可以分为以下四种范畴:
1. 线程管理:负责线程的创建,分发,等待等,以及设置/获取线程属性
2. 互斥量:使用 mutex 进行线程同步,包括mutex的创建,销毁,加锁和解锁,以及 mutex 的属性设置
3. 条件变量 :基于开发者指定的条件, 处理使用 mutex进行通信,包括condition variable的创建,销毁, 等待和通知,以及 属性设置
4. 同步:用于管理读写锁和屏障( barriers)

从函数的命名可以更清楚地了解这些分类:

Routine Prefix Functional Group
pthread_ Threads themselves and miscellaneous subroutines
pthread_attr_ Thread attributes objects
pthread_mutex_ Mutexes
pthread_mutexattr_ Mutex attributes objects.
pthread_cond_ Condition variables
pthread_condattr_ Condition attributes objects
pthread_key_ Thread-specific data keys
pthread_rwlock_ Read/write locks
pthread_barrier_ Synchronization barriers

具体后面将会分别介绍。以下是一个Pthread 基本使用的例子

#include <unistd.h>
#include <errno.h>
#include <pthread.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static const int ntimes = 10;

void* threadfunc(void* arg)
{
    pthread_t tid = pthread_self();

//  int ret;
//      if(0 != (ret=pthread_detach(tid))) {
//          fprintf(stderr, "pthread_detach:%s\n", strerror(ret));
//      exit(EXIT_FAILURE);
//      }

    printf("Thread B %#lx starting\n", (size_t)tid);

    int i;
    for(i=0; i<ntimes; ++i) {
        printf("[B-%d]", i);
        fflush(stdout);
        if(3 == i) {
            pthread_exit("Thread B breaked");   
        }
    }

    return "Thread B findshed!";
}

int main()
{
        pthread_t tid; //thread B TID
        int ret;
        if(0 != (ret=pthread_create(&tid, NULL, threadfunc, NULL))) {
            fprintf(stderr, "pthread_create:%s\n", strerror(ret));
        exit(EXIT_FAILURE);
        }

    printf("Thread A %#lx starting\n", (size_t)pthread_self());

    int i;
    for(i=0; i<ntimes; ++i) {
        printf("[A-%d]", i);
        fflush(stdout);
    }
    printf("\n");

    // 不可与 pthread_detach 同时使用,且 pthread_join 一般用在线程处理函数外
    void *value_ptr;
        if(0 != (ret=pthread_join(tid, &value_ptr))) {
            fprintf(stderr, "pthread_join:%s\n", strerror(ret));
        exit(EXIT_FAILURE);
        }
    printf("Receive msg: %s\n", (char*)value_ptr);

    exit(EXIT_SUCCESS);
}

编译运行:

gcc -o proc demo1.c -lpthread

这里写图片描述

上例中程序首先调用pthread_create函数创建线程,并为新线程设置回调函数 threadfunc,新线程创建完毕后,主线程继续执行,新线程并行执行,并各自输出相应的信息,新线程调用 pthread_exit 退出,主线程调用pthread_join函数等待新线程结束。要注意的是:pthread 函数出错时并不会更改全局变量 errno 对它进行错误处理时要注意。
这里对比一下Pthread 和系统进程管理API:

Process Thread
fork pthread_create
getpid pthread_self
waitpid pthread_join
kill pthread_exit

简要介绍程序使用到的 Pthread 函数:

int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void *), void *restrict arg);

用于创建一个新线程,参数thread是新线程的 ID,attr用于指定线程的属性,一般可以用 NULL,表示使用默认属性。start_routine和 arg 是线程回调函数和参数。

    pthread_t pthread_self(void);

返回调用线程的线程 ID

 int  pthread_join(pthread_t thread, void **value_ptr);

等待线程退出。参数value_ptr用于存储 pthread_exit 传递的信息,该函数用在线程回调函数外,而另一个函数 pthread_detach一般用在回调函数中。

int  pthread_detach(pthread_t thread);

分离线程一般用在回调函数中,在线程执行结束后,线程分配内存即被回收,避免产生僵尸线程

 void  pthread_exit(void *value_ptr);

终止线程,并将 value_ptr 传递给该线程的pthread_join函数。注意除main函数以外的线程的回调函数在返回时会隐式调用该函数

推荐一个 Pthread 学习网站:https://computing.llnl.gov/tutorials/pthreads/#MutexLocking
并行编程: https://computing.llnl.gov/tutorials/parallel_comp/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章