Posix线程编程指南(经典)
- 格式:doc
- 大小:206.50 KB
- 文档页数:18
在POSIX 线程编程中避免内存泄漏检测和避免POSIX 线程内存泄漏的技巧Wei Dong Xie, IBM Systems Director 产品工程师, IBM简介: POSIX 线程(pthread)编程定义了一套标准的C 编程语言类型、函数和常量—且pthreads 提供了一种强大的线程管理工具。
要充分使用pthreads,您要避免常见错误。
一个常见的错误就是忘记联接可接合的线程,从而导致内存泄漏并增加工作量。
在该篇技巧型文章中,学习POSIX 线程基础,了解如何识别和检测线程内存泄漏,并获得避免出现这种情况的可靠建议。
POSIX 线程简介使用线程的主要原因是要提高程序性能。
线程的创建和管理只需要较小的操作系统开销和较少的系统资源。
一个进程内的所有线程共享相同的地址空间,使得线程间的通信更高效,且比进程间通信更易于实现。
例如,如果一个线程在等待一个输入/输出系统调用完成,其他线程可以处理CPU 密集型任务。
通过线程,可以优先调度重要任务—甚至中断—低优先级任务。
可将偶尔发生的任务放在定期调度的任务之间,创建调度灵活性。
最后,pthreads 是在多CPU 计算机上进行并行编程的理想之选。
而且使用POSIX 线程或pthreads 的主要原因更加简单:作为标准C 语言线程编程接口的一部分,它们可高可移植的。
POSIX 线程编程有诸多优势,但是如果您不明确一些基本规则,就有可能编写一些难以调试的代码并造成内存泄漏。
我们首先回顾一下POSIX 线程,分为可接合线程或分离线程。
可接合线程如果您希望生成一个新的线程,且需要知道它是如何终止的,那么您需要一个可接合线程。
对于可接合线程,系统分配专用存储器来存储线程终止状态。
线程终止后状态得到更新。
要获得线程终止状态,调用pthread_join(pthread_t thread, void** value_ptr)。
系统为每个线程分配底层存储,包括堆栈、线程ID、线程终止状态等。
Linux系统编程中的POSIX标准Linux系统编程在很长一段时间内一直在不断发展,随着POSIX标准的出现,Linux系统在该方面得到了全面的支持。
POSIX标准使得不同的Unix系统和其他操作系统之间的可移植性得到了很大的提高,这是Linux系统编程所必需的。
什么是POSIX?POSIX(Portable Operating System Interface,可移植操作系统接口)是由IEEE(Institute of Electrical and Electronics Engineers,电气和电子工程师学会)开发的一系列接口标准。
1990年,IEEE 正式颁发了POSIX标准的第一个版本,这个标准定义了许多操作系统接口的规范性要求,使得Unix的不同版本之间的软件可以轻松地进行移植。
POSIX标准的主旨是定义一组标准操作系统接口,使得应用程序的可移植性更好。
POSIX标准定义了一组与操作系统交互的API,包括文件操作、进程管理、信号传递等等。
POSIX标准在Linux中的应用在Linux系统中,POSIX标准已经得到了广泛的应用。
许多Linux上的C库都以POSIX标准为基础进行开发,例如glibc、bionic等等。
这些C库包含了POSIX标准中定义的一系列API,并提供了一些额外的功能。
开发者在编写应用程序时,可以使用这些API,从而使得应用程序更加规范,并且在其他系统上的移植性更好。
POSIX标准还提供了一个实现的方式,也就是POSIX兼容层。
POSIX兼容层是一个在Linux内核中的模块,它提供了一些非标准的API,这些API能够向后兼容POSIX标准。
这个兼容层让系统具有了更好的兼容性,比如在系统上运行一些遵循POSIX标准的旧应用程序时,可以使用这些非标准API进行支持。
在Linux系统中,可以使用一些工具来检查应用程序是否严格遵循了POSIX标准。
例如lint和splint工具,它们可以自动分析源代码,并提供一些有用的警告信息和其他功能。
off是要映射字节在文件中的起始偏移量。
通常将其设置为0。
prot参数说明对映射存储区的保护要求。
可将prot参数指定为PROT_NONE,或者是PROT_READ(映射区可读),PROT_WRITE(映射区可写),PROT_EXEC(映射区可执行)任意组合的按位或,也可以是PROT_NONE(映射区不可访问)。
对指定映射存储区的保护要求不能超过文件open模式访问权限。
flag参数影响映射区的多种属性:MAP_FIXED返回值必须等于addr.因为这不利于可移植性,所以不鼓励使用此标志。
MAP_SHARED这一标志说明了本进程对映射区所进行的存储操作的配置。
此标志指定存储操作修改映射文件。
MAP_PRIVATE本标志导致对映射区建立一个该映射文件的一个私有副本。
所有后来对该映射区的引用都是引用该副本,而不是原始文件。
要注意的是必须指定MAP_FIXED或MAP_PRIVATE标志其中的一个,指定前者是对存储映射文件本身的一个操作,而后者是对其副本进行操作。
mmap成功返回后,fd参数可以关闭。
该操作对于由mmap建立的映射关系没有影响。
为从某个进程的地址空间删除一个映射关系,我们调用munmap.2.名称::munmap功能:解除存储映射头文件:#include<sys/mman.h>函数原形:int munmap(caddr_t addr,size_t len);参数:addr指向映射存储区的起始地址len映射的字节返回值:若成功则返回0,若出错则返回-1其中addr参数是由mmap返回的地址,len是映射区的大小。
再次访问这些地址导致向调用进程产生一个SIGSEGV信号。
如果被映射区是使用MAP_PRIVATE标志映射的,那么调用进程对它所作的变动都被丢弃掉。
内核的虚存算法保持内存映射文件(一般在硬盘上)与内存映射区(在内存中)的同步(前提它是MAP_SHARED内存区)。
这就是说,如果我们修改了内存映射到某个文件的内存区中某个位置的内容,那么内核将在稍后某个时刻相应地更新文件。
POSIX 线程详解 1POSIX(可移植操作系统接口)线程是提高代码响应和性能的有力手段。
在本系列中,Daniel Robbins 向您精确地展示在编程中如何使用线程。
其中还涉及大量幕后细节,读完本系列文章,您完全可以运用POSIX 线程创建多线程程序。
线程是有趣的了解如何正确运用线程是每一个优秀程序员必备的素质。
线程类似于进程。
如同进程,线程由内核按时间分片进行管理。
在单处理器系统中,内核使用时间分片来模拟线程的并发执行,这种方式和进程的相同。
而在多处理器系统中,如同多个进程,线程实际上一样可以并发执行。
那么为什么对于大多数合作性任务,多线程比多个独立的进程更优越呢?这是因为,线程共享相同的内存空间。
不同的线程可以存取内存中的同一个变量。
所以,程序中的所有线程都可以读或写声明过的全局变量。
如果曾用 fork() 编写过重要代码,就会认识到这个工具的重要性。
为什么呢?虽然 fork() 允许创建多个进程,但它还会带来以下通信问题: 如何让多个进程相互通信,这里每个进程都有各自独立的内存空间。
对这个问题没有一个简单的答案。
虽然有许多不同种类的本地 IPC (进程间通信),但它们都遇到两个重要障碍:强加了某种形式的额外内核开销,从而降低性能。
对于大多数情形,IPC 不是对于代码的“自然”扩展。
通常极大地增加了程序的复杂性。
双重坏事: 开销和复杂性都非好事。
如果曾经为了支持 IPC 而对程序大动干戈过,那么您就会真正欣赏线程提供的简单共享内存机制。
由于所有的线程都驻留在同一内存空间,POSIX 线程无需进行开销大而复杂的长距离调用。
只要利用简单的同步机制,程序中所有的线程都可以读取和修改已有的数据结构。
而无需将数据经由文件描述符转储或挤入紧窄的共享内存空间。
仅此一个原因,就足以让您考虑应该采用单进程/多线程模式而非多进程/单线程模式。
线程是快捷的不仅如此。
线程同样还是非常快捷的。
与标准 fork() 相比,线程带来的开销很小。
POXIS线程编程指南杨沙洲(************)2001 年 10 月第一篇线程创建与取消这是一个关于Posix线程编程的专栏。
作者在阐明概念的基础上,将向您详细讲述Posix线程库API。
本文是第一篇将向您讲述线程的创建与取消。
一、线程创建1.1 线程与进程相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
在串行程序基础上引入线程和进程是为了提高程序的并发度,从而提高程序运行效率和响应时间。
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。
同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。
1.2 创建线程POSIX通过pthread_create()函数创建线程,API定义如下:int pthread_create(pthread_t * thread, pthread_attr_t * attr,void * (*start_routine)(void *), void * arg)与fork()调用创建一个进程的方法不同,pthread_create()创建的线程并不具备与主线程(即调用pthread_create()的线程)同样的执行序列,而是使其运行start_routine(arg)函数。
thread 返回创建的线程ID,而attr是创建线程时设置的线程属性(见下)。
pthread_create()的返回值表示线程创建是否成功。
尽管arg是void *类型的变量,但它同样可以作为任意类型的参数传给start_routine()函数;同时,start_routine()可以返回一个void *类型的返回值,而这个返回值也可以是其他类型,并由pthread_join()获取。
1.3 线程创建属性pthread_create()中的attr参数是一个结构指针,结构中的元素分别对应着新线程的运行属性,主要包括以下几项:__detachstate,表示新线程是否与进程中其他线程脱离同步,如果置位则新线程不能用pthread_join()来同步,且在退出时自行释放所占用的资源。
多线程编程之:Linux线程编程9.2 线程编程9.2.1 线程基本编程这里要讲的线程相关操作都是用户空间中的线程的操作。
在Linux中,普通pthread线程库是一套通用的线程库,是由POSIX提出的,因此具有很好的可移植性。
(1)函数解释。
创建线程事实上就是确定调用该线程函数的入口点,这里通常用法的函数是pthread_create()。
在线程创建以后,就开头运行相关的线程函数,在该函数运行完之后,该线程也就退出了,这也是线程退出一种办法。
另一种退出线程的办法是用法函数pthread_exit(),这是线程的主动行为。
这里要注重的是,在用法线程函数时,不能任意用法exit()退出函数举行出错处理,因为exit()的作用是使调用进程终止,往往一个进程包含多个线程,因此,在用法exit()之后,该进程中的全部线程都终止了。
因此,在线程中就可以用法pthread_exit()来代替进程中的exit()。
因为一个进程中的多个线程是分享数据段的,因此通常在线程退出之后,退出线程所占用的资源并不会随着线程的终止而得到释放。
正如进程之间可以用wait()系统调用来同步终止并释放资源一样,线程之间也有类似机制,那就是pthread_join()函数。
pthread_join()可以用于将当前线程挂起来等待线程的结束。
这个函数是一个线程堵塞的函数,调用它的函数将向来等待到被等待的线程结束为止,当函数返回时,被等待线程的资源就被收回。
前面已提到线程调用pthread_exit()函数主动终止自身线程。
但是在无数线程应用中,常常会碰到在别的线程中要终止另一个线程的执行的问题。
此时调用pthread_cancel()函数实现这种功能,但在被取消的线程的内部需要调用pthread_setcancel()函数和pthread_setcanceltype()函数设置自己的取消状态,例如被取消的线第1页共9页。
pthread编程基础Linux系统下的多线程遵循POSIX线程接口,称为pthread。
编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。
与vxworks上任务的概念类似,都是调度的最小单元,都有共享的堆、栈、代码区、全局变量等。
2. 创建线程int pthread_create(pthread_t * thread,pthread_attr_t * attr,void * (*start_routine)(void *),void * arg)thread:返回创建的线程的IDattr:线程属性,调度策略、优先级等都在这里设置,如果为NULL则表示用默认属性start_routine:线程入口函数,可以返回一个void*类型的返回值,该返回值可由pthread_join()捕获arg:传给start_routine的参数,可以为NULL返回值:成功返回03. 设置线程属性线程属性通过attr进行设置。
设置与查询attr结构的为pthread_attr_get***()与pthread_attr_set***()两个函数系列。
设置与查询线程参数的为pthread_get***()与pthread_set***()两个函数系列。
也可以在创建时通过pthrea_create传入参数。
注:有些必须在线程创建时设置,如调度策略。
3.1. 调度策略调度策略有三种:SCHED_OTHER:非实时、正常SCHED_RR:实时、轮询法SCHED_FIFO:实时、先入先出,与vxworks的调度机制一致例程:pthread_attr_t attr;pthread_attr_init(&attr);pthread_attr_setschedpolicy(&attr,SCHED_FIFO);//sched_policy3.2. 优先级线程优先级支持两种设置方式,一种是创建时设置,另一种是创建后动态设置例程:pthread_attr_setschedparam(&attr, new_priority);如果是静态设置,则之后会用该属性创建任务,如果是动态设置,则使用下列函数设置:pthread_attr_setschedparam(&attr, &task->prv_priority);pthread_attr_getschedparam(&attr, &schedparam);schedparam.sched_priority = new_priority;pthread_attr_setschedparam(&attr, &schedparam);pthread_setschedparam(pthrid, sched_policy, &schedparam);3.3. 脱离同步Pthread_join()函数可以使主线程与子线程保持同步。
一.什么是线程在一个程序里的多个执行路线就叫做线程。
更准确的定义是:线程是“一个进程内部的一个控制序列”。
典型的unix进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情。
有了多个控制线程以后,在程序设计时可以把进程设计成在同一时刻能够做不止一件事,每个线程处理各只独立的任务。
二.线程的优点(1)通过为每种事件类型的处理分配单独的线程,能够简化处理异步时间的代码。
(2)多个线程可以自动共享相同的存储地址空间和文件描述符。
(3)有些问题可以通过将其分解从而改善整个程序的吞吐量。
(4)交互的程序可以通过使用多线程实现相应时间的改善,多线程可以把程序中处理用户输入输出的部分与其它部分分开。
三.线程的缺点线程也有不足之处。
编写多线程程序需要更全面更深入的思考。
在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的。
调试一个多线程程序也比调试一个单线程程序困难得多。
四.线程的结构线程包含了表示进程内执行环境必需的信息,其中包括进程中标识线程的线程ID,一组寄存器值、栈、调度优先级和策略、信号屏蔽子,errno变量以及线程私有数据。
进程的所有信息对该进程的所有线程都是共享的,包括可执行的程序文本,程序的全局内存和堆内存、栈以及文件描述符。
五.线程标识就像每个进程有一个进程ID一样,每个线程也有一个线程ID,进程ID在整个系统中是唯一的,但线程不同,线程ID只在它所属的进程环境中有效。
线程ID用pthread_t数据类型来表示,实现的时候可以用一个结构来代表pthread_t数据类型,所以可以移植的操作系统不能把它作为整数处理。
因此必须使用函数来对来对两个线程ID进行比较。
1.名称:pthread_equal功能:比较两个线程ID头文件:#include <pthread.h>函数原形:int pthread_equal(pthread_t tid1,pthread_t tid2);参数:tid1 进程1id, tid2 进程2id返回值:若相等返回非0值,否则返回02.名称:pthread_self功能:获取自身线程的id头文件:#include <pthread.h>函数原形:pthread_t pthread_self(void);参数:无返回值:调用线程的线程id六.线程的创建3.名称: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);参数:返回值:若成功返回则返回0,否则返回错误编号当pthread_creat成功返回时,tidp指向的内存单元被设置为新创建线程的线程ID。
Posix线程编程指南Posix线程编程指南 (1)一线程创建与取消 (3)线程创建 (3)1.线程与进程 (3)2. 创建线程 (3)3. 线程创建属性 (3)4. 创建的Linux实现 (4)线程取消 (4)1. 消的定义 (4)2. 线程取消的语义 (4)3. 取消点 (5)4. 程序设计方面的考虑 (5)5. 与线程取消相关的pthread函数 (5)二线程私有数据 (5)1. 概念及作用 (6)2. 创建和注销 (6)3. 访问 (6)4. 使用范例 (7)三线程同步 (8)互斥锁 (8)1.创建和销毁 (8)2.互斥锁属性 (9)3.锁操作 (9)4.其他 (9)条件变量 (10)1.创建和注销 (10)2.等待和激发 (10)3.其他 (11)信号灯 (12)1.创建和注销 (12)2.点灯和灭灯 (13)3.获取灯值 (13)4.其他 (13)异步信号 (13)其他同步方式 (14)四线程终止 (14)线程终止方式 (14)线程终止时的清理 (14)线程终止的同步及其返回值 (16)关于pthread_exit()和return (16)五杂项 (16)获得本线程ID (17)判断两个线程是否为同一线程 (17)仅执行一次的操作 (17)一线程创建与取消这是一个关于Posix线程编程的专栏。
作者在阐明概念的基础上,将向您详细讲述Posix线程库API。
本文是第一篇将向您讲述线程的创建与取消。
线程创建1.线程与进程相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
在串行程序基础上引入线程和进程是为了提高程序的并发度,从而提高程序运行效率和响应时间。
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。
同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。
2. 创建线程POSIX通过pthread_create()函数创建线程,API定义如下:与fork()调用创建一个进程的方法不同,pthread_create()创建的线程并不具备与主线程(即调用pthread_create()的线程)同样的执行序列,而是使其运行start_routine(arg)函数。
thread返回创建的线程ID,而attr是创建线程时设置的线程属性(见下)。
pthread_create()的返回值表示线程创建是否成功。
尽管arg是void *类型的变量,但它同样可以作为任意类型的参数传给start_routine()函数;同时,start_routine()可以返回一个void *类型的返回值,而这个返回值也可以是其他类型,并由pthread_join()获取。
3. 线程创建属性pthread_create()中的attr参数是一个结构指针,结构中的元素分别对应着新线程的运行属性,主要包括以下几项:__detachstate,表示新线程是否与进程中其他线程脱离同步,如果置位则新线程不能用pthread_join()来同步,且在退出时自行释放所占用的资源。
缺省为PTHREAD_CREATE_JOINABLE状态。
这个属性也可以在线程创建并运行以后用pthread_detach()来设置,而一旦设置为PTHREAD_CREATE_DETACH 状态(不论是创建时设置还是运行时设置)则不能再恢复到PTHREAD_CREATE_JOINABLE状态。
__schedpolicy,表示新线程的调度策略,主要包括SCHED_OTHER(正常、非实时)、SCHED_RR (实时、轮转法)和SCHED_FIFO(实时、先入先出)三种,缺省为SCHED_OTHER,后两种调度策略仅对超级用户有效。
运行时可以用过pthread_setschedparam()来改变。
__schedparam,一个struct sched_param结构,目前仅有一个sched_priority整型变量表示线程的运行优先级。
这个参数仅当调度策略为实时(即SCHED_RR或SCHED_FIFO)时才有效,并可以在运行时通过pthread_setschedparam()函数来改变,缺省为0。
__inheritsched,有两种值可供选择:PTHREAD_EXPLICIT_SCHED和PTHREAD_INHERIT_SCHED,前者表示新线程使用显式指定调度策略和调度参数(即attr中的值),而后者表示继承调用者线程的值。
缺省为PTHREAD_EXPLICIT_SCHED。
__scope,表示线程间竞争CPU的范围,也就是说线程优先级的有效范围。
POSIX的标准中定义了两个值:PTHREAD_SCOPE_SYSTEM和PTHREAD_SCOPE_PROCESS,前者表示与系统中所有线程一起竞争CPU时间,后者表示仅与同进程中的线程竞争CPU。
目前LinuxThreads仅实现了PTHREAD_SCOPE_SYSTEM一值。
pthread_attr_t结构中还有一些值,但不使用pthread_create()来设置。
为了设置这些属性,POSIX定义了一系列属性设置函数,包括pthread_attr_init()、pthread_attr_destroy()和与各个属性相关的pthread_attr_get---/pthread_attr_set---函数。
4. 创建的Linux实现我们知道,Linux的线程实现是在核外进行的,核内提供的是创建进程的接口do_fork()。
内核提供了两个系统调用__clone()和fork(),最终都用不同的参数调用do_fork()核内API。
当然,要想实现线程,没有核心对多进程(其实是轻量级进程)共享数据段的支持是不行的,因此,do_fork()提供了很多参数,包括CLONE_VM(共享内存空间)、CLONE_FS(共享文件系统信息)、CLONE_FILES(共享文件描述符表)、CLONE_SIGHAND(共享信号句柄表)和CLONE_PID(共享进程ID,仅对核内进程,即0号进程有效)。
当使用fork系统调用时,内核调用do_fork()不使用任何共享属性,进程拥有独立的运行环境,而使用pthread_create()来创建线程时,则最终设置了所有这些属性来调用__clone(),而这些参数又全部传给核内的do_fork(),从而创建的"进程"拥有共享的运行环境,只有栈是独立的,由__clone()传入。
Linux线程在核内是以轻量级进程的形式存在的,拥有独立的进程表项,而所有的创建、同步、删除等操作都在核外pthread库中进行。
pthread库使用一个管理线程(__pthread_manager(),每个进程独立且唯一)来管理线程的创建和终止,为线程分配线程ID,发送线程相关的信号(比如Cancel),而主线程(pthread_create())的调用者则通过管道将请求信息传给管理线程。
线程取消1. 消的定义一般情况下,线程在其主体函数退出的时候会自动终止,但同时也可以因为接收到另一个线程发来的终止(取消)请求而强制终止。
2. 线程取消的语义线程取消的方法是向目标线程发Cancel信号,但如何处理Cancel信号则由目标线程自己决定,或者忽略、或者立即终止、或者继续运行至Cancelation-point(取消点),由不同的Cancelation状态决定。
线程接收到CANCEL信号的缺省处理(即pthread_create()创建线程的缺省状态)是继续运行至取消点,也就是说设置一个CANCELED状态,线程继续运行,只有运行至Cancelation-point的时候才会退出。
3. 取消点根据POSIX标准,pthread_join()、pthread_testcancel()、pthread_cond_wait()、pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及read()、write()等会引起阻塞的系统调用都是Cancelation-point,而其他pthread函数都不会引起Cancelation动作。
但是pthread_cancel的手册页声称,由于LinuxThread库与C库结合得不好,因而目前C库函数都不是Cancelation-point;但CANCEL信号会使线程从阻塞的系统调用中退出,并置EINTR错误码,因此可以在需要作为Cancelation-point的系统调用前后调用pthread_testcancel(),从而达到POSIX标准所要求的目标,即如下代码段:4. 程序设计方面的考虑如果线程处于无限循环中,且循环体内没有执行至取消点的必然路径,则线程无法由外部其他线程的取消请求而终止。
因此在这样的循环体的必经路径上应该加入pthread_testcancel()调用。
5. 与线程取消相关的pthread函数int pthread_cancel(pthread_t thread)发送终止信号给thread线程,如果成功则返回0,否则为非0值。
发送成功并不意味着thread会终止。
int pthread_setcancelstate(int state, int *oldstate)设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信号继续运行;old_state如果不为NULL则存入原来的Cancel状态以便恢复。
int pthread_setcanceltype(int type, int *oldtype)设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。
void pthread_testcancel(void)检查本线程是否处于Canceld状态,如果是,则进行取消动作,否则直接返回。
二线程私有数据这是一个关于Posix线程编程的专栏。
作者在阐明概念的基础上,将向您详细讲述Posix线程库API。
本文是第二篇将向您讲述线程的私有数据。
1. 概念及作用在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据。