linux多线程学习[转]

GNU/Linux 实现了 POSIX 标准线程 API(所谓 pthreads)。所有线程函数和数据类型都在 <pthread.h> 头文件中声明。这些线程相关的函数没有被包含在 C 标准库中,而是在 libpthread 中,所以当链接程序的时候需在命令行中加入 -lpthread 以确保能正确链接。
  在c或c++程序中,线程ID被表示为pthread_t类型的值。创建线程时,线程函数接受一个void*类型的参数,并且返回void*类型。函数pthread_create负责创建新线程。你需要提供给他如下信息 :
1、一个指向pthread_t类型变量的指针;新线程的线程ID将存储在这里。
2、一个指向线程属性对象的指针,这个对象控制着新线程与程序其他部分交互的具体细节。如果传递NULL作为线程属性,新线程将被赋予一组默认线程属性。
3、一个指向线程函数的指针。这是一个普通的函数指针,类型如下:
      void*(*)(void*)
4、一个线程参数,类型void*。不论你传递什么值作为这个参数,当线程开始执行的时候,他都会被直接传递给新的线程。

   以下程序创建一个不断输出 x 到标准错误输出的线程。在执行 pthread_create
之后,主线程不断输出 o 到标准错误输出。

#i nclude <pthread.h>
#i nclude <stdio.h>
/* 打印 x 到错误输出。没有使用参数。不返回数据。*/
void* print_xs (void* unused)
{
while (1)
fputc ('x', stderr);
return NULL;
}
/* 主程序 */
int main ()
{
pthread_t thread_id;
/* 传教新线程。新线程将执行 print_xs 函数。*/
pthread_create (&thread_id, NULL, *print_xs, NULL);
/* 不断输出 o 到标准错误输出。*/
while (1)
fputc ('o', stderr);
return 0;
}

使用以下命令编译链接这个程序:
% cc -o thread-create thread-create.c -lpthread

等待线程 (Joining Threads)

pthread_join。它接受两个参数:线程 ID,和一个指向void*类型变量的指针,用于接收线程的返回值。如果你对线程的返回值不感兴趣,则将NULL作为第二个参数。
pthread_create (&thread2_id, NULL, &char_print, &thread2_args);
pthread_join (thread2_id, NULL);

线程返回值
如果传递给pthread_join的第二个参数不是 NULL,则线程返回值会被存储在这个指针指向的内存空间中。线程返回值,与线程变量一样,也是void*类型。如果你想要返回一个int或者其它小数字,你可以简单地把这个数值强制转换成void*指针并返回,并且在调用pthread_join之后把得到的结果转换回相应的类型1。
列表  中的程序在一个单独线程中计算第n个质数。这个线程会将得到的质数作为返回值传回主线程。与此同时,主线程可以执行其它的代码。注意,compute_prime函数中使用的连续进行除法的算法是非常低效的;如果你需要在你的程序中计算很多质数,请参考有关数值算法的书。
列表 (primes.c) 在线程中计算质数
#i nclude <pthread.h>
#i nclude <stdio.h>
/*(非常低效地)计算连续的质数。返回第N个质数。N是由 *ARG 指向的参数。*/
void* compute_prime (void* arg)
{
int candidate = 2;
int n = *((int*) arg);
while (1) {
int factor;
int is_prime = 1;
/*用连续除法检测是否为质数。*/
for (factor = 2; factor < candidate; ++factor)
if (candidate % factor == 0) {
is_prime = 0;
break;
}
/*这个质数是我们寻找的么? */
if (is_prime) {
if (--n == 0)
/*将所求的质数作为线程返回值传回。*/
return (void*) candidate;
}
++candidate;
}
return NULL;
}
int main ()
{
pthread_t thread;
int which_prime = 5000;
int prime;
/*开始计算线程,求取第 5000 个质数。*/
pthread_create (&thread, NULL, &compute_prime, &which_prime);
/*在这里做其它的工作……*/
/*等待计算线程的结束,并且取得结果。*/
pthread_join (thread, (void*) &prime);
/*输出所求得的最大质数。*/
printf("The %dth prime number is %d./n", which_prime, prime);
return 0;
}

关于线程 ID 的更多信息
有时候,一段代码需要确定是哪个线程正在执行到这里。可以通过pthread_self函数获取调用线程 ID。所得到的线程ID可以用pthread_equal函数与其它线程ID进行比较。
这些函数可以用于检测当前线程ID是否为一特定线程ID。例如,一个线程利用pthread_join等待自身是错误的。(在这种情况下,pthread_join会返回错误码EDEADLK。)
要事前发现这个情况,可以用这样的代码进行判断:
if (!pthread_equal (pthread_self (), other_thread))
pthread_join (other_thread, NULL);

线程属性
线程属性提供了一种可以用于在细粒度调整线程行为方式的机制。试着回忆一下,pthread_create函数接受一个指向线程属性对象的指针。如果你传递NULL指针,默认线程属性被用于配置新线程。同时,你也可以通过创建并且传递一个线程属性对象来指明属性中的一些值。
要指明自定义的线程属性,你必须参照以下步骤:
1. 创建一个pthread_attr_t对象。最简单的方法是声明一个该类型的自动变量。
2. 调用pthread_attr_init,传递一个指向新创建对象的指针。这个步骤将各个属性置为默认值。
3. 修改这个对象,使各个属性包含期望的值。
4. 在调用pthread_create的时候,传递一个指向该对象的指针。
5. 调用pthread_attr_destroy释放这个属性对象。这个pthread_attr_t对象本身不会被释放;可以通过pthread_attr_init将其重新初始化
程序:
int main ()
{
pthread_attr_t attr;
pthread_t thread;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread, &attr, &thread_function, NULL);
pthread_attr_destroy (&attr);
/* 进行其它工作……*/
/* 不需要等待第二个线程 */
return 0;
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值