Linux多线程
Linux多线程编程
#include <pthread.h>
基本线程函数
int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*func)(void *), void *arg);
线程创建成功返回0,出错返回某个非0值,一般为-1
tid 创建成功的线程通过tid指针返回线程ID
attr 指定线程的属性
func 线程的入口函数
arg 传递给线程的参数
int pthread_join(pthread_t *tid, void **status);
tid 必须指定的要等待的线程的ID
status 如果非空,则等待线程的返回值(一个指向某个对象的指针)存入status指向的位置
pthread_t pthread_self();
线程获取自身的线程ID函数
int pthread_detach(pthread_t tid);
一个线程是joinable(默认值),或是detached,当一个joinable的线程终止时,它的线程ID
和退出状态将留存到另一个线程对它调用pthread_join。detached的线程却像守护进程,当它
们终止时,所有相关资源都被释放,detached的线程是不能被等待终止的。
void pthread_exit(void *status);
如果一个线程没有detached,它的线程ID和退出状态将留存到另一个线程对它调用pthread_join。
status指针不能指向调用线程的局部对象,因为线程终止该资源也被释放掉。
线程终止其它方式:
线程的入口函数返回,即pthread_create函数的第三个参数。
进程main函数调用exit,进程终止,当然其中所有线程就终止。
给新线程传递参数
典型错误代码:
main ()
{
int confd;
. . . . . .
while(1)
{
. . . . . .
confd = accept(listenfd, cliaddr, &len);
pthread_create(&tid, NULL, &func, &confd);
}
}
void *func(void *arg)
{
int confd;
confd = *((int *)arg);
/*处理操作*/
}
上面参数参数传递方式是错误的。我们很容易就发现如果新线程的confd = *((int *)arg);在执行前,
accept又建立的了另一个连接并返回相应描述符存入confd,那么我们的新线程得到的只能是最后一次
accept返回的值,而之前建立的连接并未得到处理。
可以通过动态分配内存然后传递一个描述符的值来解决这个问题。
main()
{
int *ptr;
. . . . . .
while(1)
{
. . . . . .
iptr = malloc(sizeof(int));
iptr* = accept(listenfd, cliaddr, &len);
pthread_create(&tid, NULL, &func, iptr);
}
}
void *func(void *arg)
{
int confd;
confd = *((int *)arg);
free(arg);
/*处理操作*/
}
线程特定数据 & 静态变量
静态变量的特点:
1.限定同一源文件的后续代码可以访问
2.无论函数是否被调用,静态变量一直存在,不会随着函数调用退出而消失
因此当在多个线程中使用同一个函数中有静态变量时,就会涉及到静态变量的共享问题。可以使用线程特定数据解决这个问题。POSIX要求每个系统支持有限数量的线程特定数据,POSIX要求这个限制不少于128(每个进程)。系统会为每个进程维护一个称之为key的数据结构数组,如图:
当一个线程调用pthread_key_create创建线程特定数据时,系统搜索进程的key结构数组,找出第一个不在使用的元素。该元素的索引(key[i]中的i)称为key,这个索引被返回给调用线程。除了进程范围的key结构数组外,系统还在进程内维护关于每一个线程的多条信息。这些特定于线程的信息我们称之为pthread结构,其中的部分内容是我们称之为pkey数组的一个128个元素的指针数组。如图:
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。