pthread线程

本文详细介绍了POSIX线程(pthread)的管理,包括主线程的特殊性,如何分离和等待线程,互斥量的初始化和使用,条件变量的同步作用,一次性初始化,以及线程私有数据的关键概念。通过实例展示了pthread函数的使用,如pthread_detach、pthread_join、pthread_mutex和pthread_key_create等。
摘要由CSDN通过智能技术生成

《POSIX多线程程序设计》——David R.Buten

主线程是特殊的

当c语言运行时,首先执行main函数,这个特殊的执行流被称为“主线程”。主线程的特殊性在于Pthreads在main函数返回阶段保留了传统UNIX进程行为。即当进程结束时,所有线程、状态和它们的工作结果都会简单的“蒸发”——没有理由要清理什么

在大多数系统中,主线程运行在默认进程堆栈上,该堆栈可以增长到足够的尺寸;而在某些系统中,普通线程的堆栈空间是受限的,如果线程堆栈溢出,则程序会因段错误或总线错误而失败。

(例子:在main函数中调用pthread_exit,这样进程就必须等到所有线程结束后才能终止)

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#define handle_error_en(en, msg) \
    do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

static void* child_thread(void *arg) {
    while (1) { 
        printf("%lu\n", time(NULL));
        sleep(1);
    }
}

int main(void) {
    int status;
    pthread_t thread;

    status = pthread_create(&thread, NULL, child_thread, NULL);
    if (0 != status) 
        handle_error_en(status, "pthread_create");
    pthread_exit(NULL); // 主线程终止,但进程会等待所有线程结束后才终止
    return 0;
}

1

分离一个正在运行的线程不会对线程带来任何影响

分离线程仅仅是通知系统当该线程结束时,其所属资源可以被回收

  • 如果要创建一个从不需要控制的线程,可以使用属性(attribute)来建立线程以使它总是可分离的。
  • 如果不想等待创建的某个线程,而且知道不再需要控制它,可以随时调用pthread_detach函数来分离它(线程可以分离自己)。
  • 如果需要获得线程的返回值,或者需要获知其何时结束,应该调用pthread_join函数,pthread_join函数将阻塞其调用者直到指定线程终止(调用pthread_join函数自动分离指定的线程)。
  • 如果多个线程需要知道某个特定线程何时结束,则这些线程应该等待某个条件变量而不是调用pthread_join函数。

如果pthread_join恰恰实现了你想要的功能,则一定要使用它。由于pthread_join是最受限的传递返回值的模型,不要扭曲自己的设计来满足pthread_join的限制。

(例子:使用pthread_join函数和pthread_detach函数)

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define err_abort(code, text) do { \
    fprintf(stderr, "%s at \"%s\":%d: %s\n", \
        text, __FILE__, __LINE__, strerror(errno)); \
    abort(); \
    } while (0)

void * detach_thread(void *arg) {
    int status;
    status = pthread_detach(pthread_self()); // 分离自己
    if (0 != status) err_abort(status, "Detach thread");
    sleep(3); // 3s后终止
    printf("detach_thread() exit\n");
    return NULL;
}

void* join_thread(void *arg) {
    return arg;
}

int main(int argc, char *argv[]) {
    pthread_t join_id, detach_id;
    void *thread_result;
    int arg = 123;
    int status;

    status = pthread_create(&join_id, NULL, join_thread, &arg);
    if (status != 0) err_abort(status, "Create Join thread");
    status = pthread_create(&detach_id, NULL, detach_thread, NULL);
    if (status != 0) err_abort(status, "Create Detach thread");

    status = pthread_join(join_id, &thread_result); // 阻塞等待线程终止
    if (status != 0) err_abort(status, "Join thread");
    printf("thread_result=%d\n", *(int *)thread_result);

    pthread_exit(NULL); // 终止主线程,保留进程
    return 0;
}

结果:

thread_result=123
detach_thread() exit

互斥量

  • 互斥量是用pthread_mutex_t类型表示,不能拷贝互斥量变量,因为使用拷贝的互斥量是不确定的。可以拷贝指向互斥量的指针。
  • 必须保证每个互斥量在使用前被初始化,而且只被初始化一次。可以在创建任何线程之前初始化它,如通过调用pthread_once
  • Pthreads提供了pthread_mutex_trylock函数(非阻塞式互斥量),当调用互斥量已被锁住时调用该函数将立即返回错误代码EBUSY。使用pthread_mutex_trylock加锁函数时,需确保只有当此函数调用成功时,才能解锁互斥量。只有拥有互斥量的线程才能解锁它。

(trylock.c:使用pthread_mutex_trylock函数间歇性地报告计数器的值,不过仅当它对计数器的访问与计数线程没有发生冲突时才报告)

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define err_abort(code, text) do { \
    fprintf(stderr, "%s at \"%s\":%d: %s\n", \
        text, __FILE__, __LINE__, strerror(errno)); \
    abort(); \
    } while (0)

#define SPIN 1000000

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 静态初始化互斥锁
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值