pthread的使用

时间:2022-07-24
本文章向大家介绍pthread的使用,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

写一个test_pthread.c,练习pthread的用法

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>

void *thread(void *str)
{
    int i;
    for (i = 0; i < 10; ++i)
    {
        sleep(2);
        printf( "This in the thread : %dn" , i );
    }
    return NULL;
}
 
int main()
{
    pthread_t pth;
    int i;
    int ret = pthread_create(&pth, NULL, thread, NULL);
    
     pthread_join(pth, NULL);
    for (i = 0; i < 10; ++i)
    {
        sleep(1);
        printf( "This in the main : %dn" , i );
    }   
    return 0;
}

编译的时候发现,报错对‘pthread_create’未定义的引用,由于pthread库不是Linux系统默认的库,连接时需要使用库libpthread.a,所以在使用pthread_create创建线程时,在编译中要加-lpthread参数:然后重新编译

gcc -o pthread pthread_test.c -lpthread

运行

./pthread

运行结果

This in the thread : 0
This in the thread : 1
This in the thread : 2
This in the thread : 3
This in the thread : 4
This in the thread : 5
This in the thread : 6
This in the thread : 7
This in the thread : 8
This in the thread : 9
This in the main : 0
This in the main : 1
This in the main : 2
This in the main : 3
This in the main : 4
This in the main : 5
This in the main : 6
This in the main : 7
This in the main : 8
This in the main : 9

这说明:pthread_join函数的调用者在等待子线程退出后才继续执行!

pthread_join函数:

函数pthread_join用来等待一个线程的结束。 函数定义: int pthread_join(pthread_t thread, void **retval); 描述 : pthread_join()函数,以阻塞的方式等待thread指定的线程结束。当函数返回时,被等待线程的资源被收回。如果进程已经结束,那么该函数会立即返回。并且thread指定的线程必须是joinable的。

参数 : thread: 线程标识符,即线程ID,标识唯一线程。 retval: 用户定义的指针,用来存储被等待线程的返回值。 返回值 : 0代表成功。 失败,返回的则是错误号。 现在屏蔽pthread_join函数:

运行结果为:

This in the main : 0
This in the thread : 0
This in the main : 1
This in the main : 2
This in the thread : 1
This in the main : 3
This in the main : 4
This in the thread : 2
This in the main : 5
This in the main : 6
This in the thread : 3
This in the main : 7
This in the main : 8
This in the thread : 4
This in the main : 9

说明在子线程没有运行完毕,main函数就退出了。

pthread_create函数:

声明:

  int pthread_create(pthread_t *thread,

                    const pthread_attr_t *restrict_attr,

                    void*(*start_rtn)(void*),

                    void *restrict arg);

参数:

第一个参数*thread为指向线程标识符的指针。 第二个参数*restrict_attr用来设置线程属性,上面也可以用NULL,表示使用默认的属性。 第三个参数是线程运行函数的起始地址。 最后一个参数是运行函数的参数,NULL表示无参数。 另外,在编译时注意加上-lpthread参数,以调用链接库。因为pthread并非Linux系统的默认库,而是posix线程库,在Linux中将其作为一个库来使用,因此加上 -lpthread(或-pthread)以显示的链接该库。函数在执行错误时的错误信息将作为返回值返回,并不修改系统全局变量errno,当然也无法使用perror()打印错误信息。

pthread_t:pthread_t用于声明线程ID!

类型定义: typedef unsigned long int pthread_t; //come from /usr/include/bits/pthread.h sizeof (pthread_t) =4;

pthread_attr_init函数:

声明:int pthread_attr_init(pthread_attr_t*attr);

返回值:返回0,表示函数初始化对象成功。失败时返回一个错误代码。 参数:指向一个线程属性的指针。 函数例程如下:

int main(int argc, char *argv[])
{
	pthread_t tid;/*线程标示符*/
	pthread_attr_t attr;
 
	if (argc != 2)/*如果参数不为2个*/
	{
		fprintf (stderr, "usage:a.out<integer value>n");/*报错*/
		return -1;
	}
	if (atoi(argv[1] ) < 0)
	{
		fprintf (stderr, "%d must be <= 0n", atoi(argv[1]));
		return -1;
	}
	pthread_attr_init(&attr); /*初始化,得到默认的属性值*/
	pthread_create(&tid, &attr, runner, argv[1]);/*创建一个线程*/
	pthread_join(tid, NULL);/*等待子线程执行完毕*/
 
	printf ("sum = %dn", sum);
	return 0;
}
 
void *runner(void *param)/*子线程将会执行这个函数*/
{
	int i, upper = atoi(param);
	sum = 0;
	printf("upper:%dn",upper);
	for (i = 1; i <= upper; i++)
	{
		sum += i;
	}
	pthread_exit(0);
}

运行:

 ./pthread 1

得到结果

upper:1
sum = 1

如果屏蔽

//pthread_attr_init(&attr); /*初始化,得到默认的属性值*/

运行结果时,发现sum=0,没有upper值打印,说明,没有进入子线程,如果把attr变为NULL,

pthread_create(&tid, NULL, runner, argv[1]);/*创建一个线程*/

运行,输出结果又是

upper:1
sum = 1