Posix线程编程指南(5)

杨沙洲

原文地址:http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part5/

杂项

这是一个关于Posix线程编程的专栏。作者在阐明概念的基础上,将向您详细讲述Posix线程库API。本文是第五篇将向您讲述pthread_self()、pthread_equal()和pthread_once()等杂项函数。

在Posix线程规范中还有几个辅助函数难以归类,暂且称其为杂项函数,主要包括pthread_self()、pthread_equal()和pthread_once()三个,另外还有一个LinuxThreads非可移植性扩展函数pthread_kill_other_threads_np()。本文就介绍这几个函数的定义和使用。

获得本线程ID

    pthread_t pthread_self(void);

本函数返回本线程的标识符。

在LinuxThreads中,每个线程都用一个pthread_descr结构来描述,其中包含了线程状态、线程ID等所有需要的数据结构,此函数的实现就是在线程栈帧中找到本线程的pthread_descr结构,然后返回其中的p_tid项。

pthread_t类型在LinuxThreads中定义为无符号长整型。

判断两个线程是否为同一线程

    int pthread_equal(pthread_t thread1, pthread_t thread2);

判断两个线程描述符是否指向同一线程。在LinuxThreads中,线程ID相同的线程必然是同一个线程,因此,这个函数的实现仅仅判断thread1和thread2是否相等。

仅执行一次的操作

    int pthread_once(pthread_once_t *once_control, void (*init_routine) (void));

本函数使用初值为PTHREAD_ONCE_INIT的once_control变量保证init_routine()函数在本进程执行序列中仅执行一次。

    #include <stdio.h>
#include <pthread.h>
pthread_once_t once=PTHREAD_ONCE_INIT;
void once_run(void)
{
printf("once_run in thread %d\n",pthread_self());
}
void * child1(void *arg)
{
int tid=pthread_self();
printf("thread %d enter\n",tid);
pthread_once(&once,once_run);
printf("thread %d returns\n",tid);
}
void * child2(void *arg)
{
int tid=pthread_self();
printf("thread %d enter\n",tid);
pthread_once(&once,once_run);
printf("thread %d returns\n",tid);
}
int main(void)
{
int tid1,tid2;
printf("hello\n");
pthread_create(&tid1,NULL,child1,NULL);
pthread_create(&tid2,NULL,child2,NULL);
sleep(10);
printf("main thread exit\n");
return 0;
}

once_run()函数仅执行一次,且究竟在哪个线程中执行是不定的,尽管pthread_once(&once,once_run)出现在两个线程中。

LinuxThreads使用互斥锁和条件变量保证由pthread_once()指定的函数执行且仅执行一次,而once_control则表征是否执行过。如果once_control的初值不是PTHREAD_ONCE_INIT(LinuxThreads定义为0),pthread_once()的行为就会不正常。在LinuxThreads中,实际"一次性函数"的执行状态有三种:NEVER(0)、IN_PROGRESS(1)、DONE(2),如果once初值设为1,则由于所有pthread_once()都必须等待其中一个激发"已执行一次"信号,因此所有pthread_once()都会陷入永久的等待中;如果设为2,则表示该函数已执行过一次,从而所有pthread_once()都会立即返回0。

pthread_kill_other_threads_np()

    void pthread_kill_other_threads_np(void);

这个函数是LinuxThreads针对本身无法实现的POSIX约定而做的扩展。POSIX要求当进程的某一个线程执行exec*系统调用在进程空间中加载另一个程序时,当前进程的所有线程都应终止。由于LinuxThreads的局限性,该机制无法在exec中实现,因此要求线程执行exec前手工终止其他所有线程。pthread_kill_other_threads_np()的作用就是这个。

需要注意的是,pthread_kill_other_threads_np()并没有通过pthread_cancel()来终止线程,而是直接向管理线程发"进程退出"信号,使所有其他线程都结束运行,而不经过Cancel动作,当然也不会执行退出回调函数。尽管LinuxThreads的实验结果与文档说明相同,但代码实现中却是用的__pthread_sig_cancel信号来kill线程,应该效果与执行pthread_cancel()是一样的,其中原因目前还不清楚。

最新文章

  1. STM32F746的RTC使用
  2. 2016 icpc-ec-final
  3. 求空间内两条直线的最近距离以及最近点的坐标(C++)
  4. 二:C语言(分之结构)
  5. DPM检测模型 VoC-release 5 linux 下编译运行
  6. Visual Studio Developer Assistant 3月新功能展示
  7. android handler调用post方法阻塞
  8. 将NuGet配置到环境变量中
  9. C语言指针与数组的定义与声明易错分析
  10. OD之窗口界面
  11. Android 通用获取Ip的方法(判断手机是否联网的方法)!!!
  12. Uber即将进驻扬州啦,车主火热招募中!
  13. Java IO流之打印流与标准流
  14. The mkdir Command
  15. 关闭PHPStorm 2017.1 中的新功能中的参数提示( Parameter hints )
  16. python 虚拟环境的搭建
  17. THE SCHOOLS WHERE APPLE, GOOGLE, AND FACEBOOK GET THEIR RECRUITS
  18. [Swift]LeetCode34. 在排序数组中查找元素的第一个和最后一个位置 | Find First and Last Position of Element in Sorted Array
  19. 用Maxima画出一些有趣的图
  20. cocos2d-x getParent() 获得一个父类的一个node型指针,转换为父类类型

热门文章

  1. 吴裕雄--天生自然Android开发学习:魅蓝3开启USB调试
  2. labview学习——生产者/消费者(数据)(事件)
  3. C++笔试常见问题
  4. haproxy笔记之六:负载均衡MySQL服务的配置示例
  5. Python-删除多级目录
  6. 利用Load命令将本地文本里面的数据导入到MySQL数据库
  7. Java 原子类 java.util.concurrent.atomic
  8. Leetcode 063 不同路径二
  9. HEALER
  10. requests库入门-16-Session和Cookie