使用POSIX pthread库进行多线程编程

在C语言中使用POSIX线程pthread实现多线程编程 在C语言中,我们可以使用POSIX线程pthread)来创建和管理线程。本文将详细介绍该中主要包含的线程管理函数和线程同步函数,并给出了示例解析 阅读详情

先请看一下这个链接 http://blog.csdn.net/benny_cen/archive/2009/03/08/3968765.aspx

紧跟有几个链接都是关于 POSIX 的多线程介绍。

 

 

 

 

 

 

http://blog.csdn.net/hwz119/archive/2007/06/14/1651552.aspx

 

11 Threads
1 Introduction
不用介绍了吧…
2 Thread Concepts
1.     Thread由下面部分组成:
a.     Thread ID
b.     Stack
c.     Policy
d.     Signal mask
e.     Errno
f.      Thread-Specific Data
3 Thread Identification
1.     pthread_t用于表示Thread ID,具体内容根据实现的不同而不同,有可能是一个Structure,因此不能将其看作为整数
2.     pthread_equal函数用于比较两个pthread_t是否相等
#include <pthread.h>
 
int pthread_equal(pthread_t tid1, pthread_t tid2)
 

3.     pthread_self函数用于获得本线程的thread id
#include <pthread.h>
 
pthread _t pthread_self(void);
 

 
4 Thread Creation
1.     创建线程可以调用pthread_create函数:
#include <pthread.h>
 
int pthread_create(
       pthread_t *restrict tidp,
       const pthread_attr_t *restrict attr,
       void *(*start_rtn)(void *), void *restrict arg);
 

a.     pthread_t *restrict tidp:返回最后创建出来的Thread的Thread ID
b.     const pthread_attr_t *restrict attr:指定线程的Attributes,后面会讲道,现在可以用NULL
c.     void *(*start_rtn)(void *):指定线程函数指针,该函数返回一个void *,参数也为void*
d.     void *restrict arg:传入给线程函数的参数
e.     返回错误值。
2.     pthread函数在出错的时候不会设置errno,而是直接返回错误值
3.     在Linux系统下面,在老的内核中,由于Thread也被看作是一种特殊,可共享地址空间和资源的Process,因此在同一个Process中创建的不同Thread具有不同的Process ID(调用getpid获得)。而在新的2.6内核之中,Linux采用了NPTL(Native POSIX Thread Library)线程模型(可以参考http://en.wikipedia.org/wiki/Native_POSIX_Thread_Libraryhttp://www-128.ibm.com/developerworks/linux/library/l-threading.html?ca=dgr-lnxw07LinuxThreadsAndNPTL),在该线程模型下同一进程下不同线程调用getpid返回同一个PID。
4.     不能对创建的新线程和当前创建者线程的运行顺序作出任何假设
5 Thread Termination
1.     exit, _Exit, _exit用于中止当前进程,而非线程
2.     中止线程可以有三种方式:
a.     在线程函数中return
b.     被同一进程中的另外的线程Cancel掉
c.     线程调用pthread_exit函数
3.     pthread_exit和pthread_join函数的用法:
a.     线程A调用pthread_join(B, &rval_ptr),被Block,进入Detached状态(如果已经进入Detached状态,则pthread_join函数返回EINVAL)。如果对B的结束代码不感兴趣,rval_ptr可以传NULL。
b.     线程B调用pthread_exit(rval_ptr),退出线程B,结束代码为rval_ptr。注意rval_ptr指向的内存的生命周期,不应该指向B的Stack中的数据。
c.     线程A恢复运行,pthread_join函数调用结束,线程B的结束代码被保存到rval_ptr参数中去。如果线程B被Cancel,那么rval_ptr的值就是PTHREAD_CANCELLED。
两个函数原型如下:
#include <pthread.h>
 
void pthread_exit(void *rval_ptr);
 
int pthread_join(pthread_t thread, void **rval_ptr);
 

4.     一个Thread可以要求另外一个Thread被Cancel,通过调用pthread_cancel函数:
#include <pthread.h>
 
void pthread_cancel(pthread_t tid)
 

该函数会使指定线程如同调用了pthread_exit(PTHREAD_CANCELLED)。不过,指定线程可以选择忽略或者进行自己的处理,在后面会讲到。此外,该函数不会导致Block,只是发送Cancel这个请求。
5.     线程可以安排在它退出的时候,某些函数自动被调用,类似atexit()函数。需要调用如下函数:
#include <pthread.h>
 
void pthread_cleanup_push(void (*rtn)(void *), void *arg);
void pthread_cleanup_pop(int execute);
 

这两个函数维护一个函数指针的Stack,可以把函数指针和函数参数值push/pop。执行的顺序则是从栈顶到栈底,也就是和push的顺序相反。
在下面情况下pthread_cleanup_push所指定的thread cleanup handlers会被调用:
a.     调用pthread_exit
b.     相应cancel请求
c.     以非0参数调用pthread_cleanup_pop()。(如果以0调用pthread_cleanup_pop(),那么handler不会被调用
有一个比较怪异的要求是,由于这两个函数可能由宏的方式来实现,因此这两个函数的调用必须得是在同一个Scope之中,并且配对,因为在pthread_cleanup_push的实现中可能有一个{,而pthread_cleanup_pop可能有一个}。因此,一般情况下,这两个函数是用于处理意外情况用的,举例如下:
void *thread_func(void *arg)
{
    pthread_cleanup_push(cleanup, “handler”)
 
    // do something
 
    Pthread_cleanup_pop(0);
    return((void *)0);
}
 

 
6.     进程函数和线程函数的相关性:
Process Primitive
 Thread Primitive
 Description
 
fork
 pthread_create
 创建新的控制流
 
exit
 pthread_exit
 退出已有的控制流
 
waitpid
 pthread_join
 等待控制流并获得结束代码
 
atexit
 pthread_cleanup_push
 注册在控制流退出时候被调用的函数
 
getpid
 pthread_self
 获得控制流的id
 
abort
 pthread_cancel
 请求非正常退出
 

7.     缺省情况下,一个线程A的结束状态被保存下来直到pthread_join为该线程被调用过,也就是说即使线程A已经结束,只要没有线程B调用pthread_join(A),A的退出状态则一直被保存。而当线程处于Detached状态之时,党线程退出的时候,其资源可以立刻被回收,那么这个退出状态也丢失了。在这个状态下,无法为该线程调用pthread_join函数。我们可以通过调用pthread_detach函数来使指定线程进入Detach状态:
#include <pthread.h>
 
int pthread_detach(pthread_t tid);
 

通过修改调用pthread_create函数的attr参数,我们可以指定一个线程在创建之后立刻就进入Detached状态
6 Thread Synchronization1.     互斥量:Mutex
a.     用于互斥访问
b.     类型:pthread_mutex_t,必须被初始化为PTHREAD_MUTEX_INITIALIZER(用于静态分配的mutex,等价于pthread_mutex_init(…, NULL))或者调用pthread_mutex_init。Mutex也应该用pthread_mutex_destroy来销毁。这两个函数原型如下:(attr的具体含义下一章讨论)
#include <pthread.h>
 
int pthread_mutex_init(
       pthread_mutex_t *restrict mutex,
       const pthread_mutexattr_t *restrict attr)
 
int pthread_mutex_destroy(pthread_mutex_t *mutex);
 

c.     pthread_mutex_lock用于Lock Mutex,如果Mutex已经被Lock,该函数调用会Block直到Mutex被Unlock,然后该函数会Lock Mutex并返回。pthread_mutex_trylock类似,只是当Mutex被Lock的时候不会Block,而是返回一个错误值EBUSY。pthread_mutex_unlock则是unlock一个mutex。这三个函数原型如下:
#include <pthread.h>
 
int pthread_mutex_lock(pthread_mutex_t *mutex);
 
int pthread_mutex_trylock(pthread_mutex_t *mutex);
 
int pthread_mutex_unlock(pthread_mutex_t *mutex);
 

 
2.     读写锁:Reader-Writer Locks
a.     多个线程可以同时获得读锁(Reader-Writer lock in read mode),但是只有一个线程能够获得写锁(Reader-writer lock in write mode)
b.     读写锁有三种状态
                                          i.    一个或者多个线程获得读锁,其他线程无法获得写锁
                                         ii.    一个线程获得写锁,其他线程无法获得读锁
                                        iii.    没有线程获得此读写锁
c.     类型为pthread_rwlock_t
d.     创建和关闭方法如下:
#include <pthread.h>
 
int pthread_rwlock_init(
       pthread_rwlock_t *restrict rwlock,
       const pthread_rwlockattr_t *restrict attr)
 
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
 

e.     获得读写锁的方法如下:
#include <pthread.h>
 
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
 
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
 
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
 
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
 
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
 

 
pthread_rwlock_rdlock:获得读锁
pthread_rwlock_wrlock:获得写锁
pthread_rwlock_unlock:释放锁,不管是读锁还是写锁都是调用此函数
注意具体实现可能对同时获得读锁的线程个数有限制,所以在调用pthread_rwlock_rdlock的时候需要检查错误值,而另外两个pthread_rwlock_wrlock和pthread_rwlock_unlock则一般不用检查,如果我们代码写的正确的话。
3.     Conditional Variable:条件
a.     条件必须被Mutex保护起来
b.     类型为:pthread_cond_t,必须被初始化为PTHREAD_COND_INITIALIZER(用于静态分配的条件,等价于pthread_cond_init(…, NULL))或者调用pthread_cond_init
#include <pthread.h>
 
int pthread_cond_init(
       pthread_cond_t *restrict cond,
       const pthread_condxattr_t *restrict attr)
 
int pthread_cond_destroy(pthread_cond_t *cond);
 

 
c.     pthread_cond_wait函数用于等待条件发生(=true)。pthread_cond_timedwait类似,只是当等待超时的时候返回一个错误值ETIMEDOUT。超时的时间用timespec结构指定。此外,两个函数都需要传入一个Mutex用于保护条件
#include <pthread.h>
 
int pthread_cond_wait(
       pthread_cond_t *restrict cond,
       pthread_mutex_t *restrict mutex);
 
int pthread_cond_timedwait(
       pthread_cond_t *restrict cond,
       pthread_mutex_t *restrict mutex,
       const struct timespec *restrict timeout);
 

 
d.     timespec结构定义如下:
struct timespec {
       time_t tv_sec;       /* seconds */
       long   tv_nsec;      /* nanoseconds */
};
 

注意timespec的时间是绝对时间而非相对时间,因此需要先调用gettimeofday函数获得当前时间,再转换成timespec结构,加上偏移量。
e.     有两个函数用于通知线程条件被满足(=true):
#include <pthread.h>
 
int pthread_cond_signal(pthread_cond_t *cond);
 
int pthread_cond_broadcast(pthread_cond_t *cond);
 

两者的区别是前者会唤醒单个线程,而后者会唤醒多个线程。
 
 

【C语言】利用指针变量作函数参数,交换两数 | 常见C语言面试题:请解释一下C语言中的多线程编程的概念和实现方式。| 基于pthreadPOSIX线程,基于Windows API的线程 引例 程序如下: #include <stdio.h> void Swap(int x,int y); int main(){ int a,b; printf("Please enter a,b: "); scanf("%d,%d",&a,&b); printf("Before Swap:a=%d,b=%d\n",a,b); Swap(a,b); printf("After Swap:a=%d,b=%d\n",a,b); return 0; } void Swap( 阅读详情

相关推荐

Linux上posix线程实现原理讨论

原文:来自论坛一处讨论http://bbs.chinaunix.net/thread-497496-2-1.html 说明一下,这个问题困扰我好长时间,因为正如使用C编程会希望了解进程的内存映象一样,使用POSIX线程我们也会想去了解其实现的原理。目前只是查过一些资料,或许仍然有误解的地方,请大家继续指正         首先我们需要了解线程(threads)是个什么概念。在传统

fengxinze的专栏 2136

pthread-win32:跨平台多线程编程在Windows的实现

在现代操作系统中,多线程编程已成为实现应用程序并行化、提高系统效率和响应速度的关键技术。POSIX线程(pthreads),作为一套定义了线程行为的API标准,广泛应用于UNIX、Linux、以及POSIX兼容的系统上。通过pthreads,开发者能够利用多线程的能力来改善程序的性能与用户体验。是一个为Windows系统提供的POSIX线程的安装程序。它允许开发者在Windows平台上使用POSIX线程API进行多线程编程,以模拟UNIX环境的线程行为。

weixin_42584758的博客 663

posix标准 pthread.h源代码

posix thread pthread.h源代码 (ubuntu16.04自带的posix thread

第七宇林的博客 2563

linux pthread 多线程编程

POSIX 标准中规范了与多线程相关的系统接口。在 Linux 系统上编写多线程程序,只需在程序中引入头文件

antRain的博客 829

使用POSIX Threads进行多线程编程(一)——pthread基本知识

使用POSIX Threads进行多线程编程——pthread基本知识说明: 本文是翻译自《MultiThreaded-Programming-With-POSIX》,作者Guy Kerens。本文预计翻译三章,主要涉及多线程基本知识、互斥量(锁)和条件变量,一是因为这已经能够引导读者入门,二是因为本人时间工作之余翻译,实在时间捉急。 翻译:张小川,转载请保留原作者 写在开始这份综述是为了使你熟悉使

小川学编程 6164

多线程编程学习笔记3】创建线程函数pthread_create()详解

申明:本学习笔记是在该教程的基础上结合自己的学习情况进行的总结,不是原创,想要看原版的请看C语言中文网的多线程编程(C语言+Linux),该网站有很多好的编程学习教程,尤其是关于C语言的。 前面章节中,我们通过调用 pthread_create() 函数成功创建了多个线程,本节就给大家详细讲解 pthread_create() 函数的用法。 pthread_create() 函数声明在<pthread.h>头文件中,语法格式如下: int pthread_create(pthread_t *.

qq_41854911的博客 1万+

windows下使用pthread

最近在看《C++多核高级编程》这本书,收集了些有用的东西,方便在windows下使用POSIX标准进行Pthread开发,有利于跨平台。--------------------------------------------------windows下使用pthread时间:2010-01-27 07:41来源:罗索工作室 作者:落鹤生 点击:1220次我听很多人都说pthreads对Windows的兼容性不好,但我又没用过,也根本不知道到底好,还是不好,只不过我看ffmpeg都有在用pthreads,而

G_Spider的专栏 2万+

linux下多线程(pthread)编程实例,Linux多线程编程实例解析

haoLinux系统下的多线程遵循POSIX线程接口,称为 pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用libpthread.a。顺便说一下,Linux 下pthread实现是通过系统调用clone()来实现的。clone()是 Linux所特有的系统调用,它的使用方式类似fork,关于clone()的详细情况,有兴趣的读者可以去查看有关文档说...

weixin_28990983的博客 250

Linux C++ pthread是什么缩写?(POSIX Threads)<pthread.h>

pthreadPOSIX 线程标准POSIX Threads)的缩写。它提供了对多线程编程的支持,是跨平台的线程,可以在多个操作系统和硬件平台上使用pthread 包含一些函数和类型定义,例如 pthread_create、pthread_joinpthread_mutex_t 和 pthread_cond_t 等。在 Linux 或类 Unix 系统下使用 pthread ,需要包含 头文件。

Dontla的博客 911

Linux开发_多线程编程

Linux下的多线程使用pthread,是一个准守POSIX接口的函数。 Linux下多线程编程对函数定义原型有要求,必须是void *函数名(void *参数名),或者void 函数名(void); 主要创建函数是: pthread_create 参数: 参数 描述 thread 指向线程标识符指针。 attr 一个不透明的属性对象,可以被用来设置线程属性。您可以指定线程属性对象,也可以使用默认值 NULL。 start_routine 线程运行函数起

17岁boy的博客 579

linux下的POSIX C 多线程编程 helloworld

#include #include #include #include #define MAX 10 pthread_t thread[2]; pthread_mutex_t mut; int number = 0; int i; void* thread1( void *param ) { printf( "thread1: I'm thread 1\n " );

辉仔 の专栏 2224

[手游新项目历程]第24天-pthread

Pthread  点击打开链接 【源码剖析】threadpool —— 基于 pthread 实现的简单线程池 点击打开链接 C语言多线程pthread相关函数说明 点击打开链接 pthread线程源代码 点击打开链接 pthread文件 点击打开链接 windows下使用pthread 点击打开链接

719

Ubuntu —— 安装 :: pthread

多线程编程用到pthread: 安装 sudo apt-get install glibc-doc 安装以后,发现还是有很多函数不全,只有一小部分pthread的函数,安装manpages-posix-dev就可以了。 sudo apt-get install manpages-posix-dev ...

xiaodouhao123456的博客 1万+

linux C++ 多线程编程

1.Solaris .vs. Linux Posix   Solaris (lib 线程) Linux POSIX (libp 线程) 操作 sema_destroy() sem_destroy() 销毁信号状态。 sema_init() sem_init() 初始化信号。 sema_post() sem_post()

jinyeweiyang的专栏 423

linux多线程设计

<br /> 摘自http://www.hudong.com/wiki/linux%E5%A4%9A%E7%BA%BF%E7%A8%8B%E8%AE%BE%E8%AE%A1linux多线程设计-简单的多线程编程    <br />Linux系统下的多线程遵循POSIX 线程接口,称为pthread。编写Linux下 的多线程程序,需要使用头文件pthread.h,连接时需要使用libpthread.a。顺便说一下,Linux下pthread实现是通过系 统调用 clone()来实现的。clone

ghost1236的专栏 1379

POSIX线程

在前面,我们介绍了如何在Linux (包括UNIX)中处理讲程。类UNIX操作系统早就具备这种多进程功能了。但有时人们认为,用fork调用来创建新进程的代价太高。在这种情况下,如果能让一个进程同时做两件事情或至少看起来是这样将会非常有用。而且,你可能希望能有两件或更多的事情以一种非常紧密的方式同时发生。这就是需要线程发挥作用的时候了。 什么是线程 **在一个程序中的多个执行路线就叫做线程(thread)。更准确的定义是:线程是一个进程内部的一个控制序列。**虽然Linux和许多其他的操作系统一样,都擅长同时

weixin_43887148的博客 1666

linux: pthread---posix线程创建使用接口&&状态

本文介绍了Linux线程编程的核心概念与实现。主要内容包括:1)线程创建与终止,通过pthread_create创建线程,使用pthread_exit或return退出,线程异常终止返回(void*)-1;2)线程等待与资源回收,pthread_join用于获取线程退出状态,pthread_detach可使线程自动释放资源;3)Linux线程实现原理,采用轻量级进程(LWP)机制,通过NPTL线程封装;4)线程取消机制,pthread_cancel通过设置标记终止线程。文章通过代码示例演示了线程创建、终止

加油! 840
上一篇: C++中虚析构函数的作用
下一篇: C++中指针和引用有什么区别?
yang_lang
博客等级 码龄16年 20粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值