Linux系统编程——线程(二)线程自身相关API 和 线程共享内存的验证

171 阅读4分钟

所有API的头文件

#include<pthread.h>

1、创建

函数原型

int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 返回:若成功返回0,否则返回错误编号

当pthread_create成功返回时

tidp:指向的内存单元被设置为新创建线程的线程ID。

attr:用于定制各种不同的线程属性,设置为NULL就是创建默认属性的线程。

start_rtn: 新创建的线程从start_rtn函数的地址开始运行,只有一个无类型指针参数arg。

arg:向start_rtn函数传递的参数,如果不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为第四个参数arg传入

2、等待

函数原型

int pthread_join(pthread_t thread, void **rval_ptr);
// 成功返回0,否则返回错误编号

thread:线程名
**rval_ptr :线程返回值

调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、如果例程只是从它的启动例程返回,rval_ptr将包含返回码。如果线程被取消,由rval_ptr指定的内存单元就置为PTHREAD_CANCELED。

如果线程的返回值不重要,可以把rval_ptr设置为NULL。再调用pthread_join函数时,将等待指定的线程终止,但并不获得线程的终止状态

3、退出

线程退出方式有三种(不终止整个进程的情况)

1)线程从启动例程中返回,返回值是线程的退出码。

2)线程可以被同一进程中的其他线程取消。

3)线程调用pthread_exit函数。

pthread_exit函数原型

int pthread_exit(void *rval_ptr);

rval_ptr是一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针
其他API

4、线程脱离

一个线程或者是可汇合(joinable,默认值),或者是脱离的(detached)。当一个可汇合的线程终止时,它的线程ID和退出状态将留存到另一个线程对它调用pthread_join。

pthread_detach函数把指定的线程转变为脱离状态。

函数原型

int pthread_detach(pthread_t thread);
// 返回:若成功返回0,否则返回错误编号

函数想让自己脱离的线程使用,就如以下语句:

int pthread_detach(pthread_self());

返回值: 成功返回0,否则返回错误编号

5. 线程ID获取

函数原型

pthread_t pthread_self(void);

返回值: 调用线程的ID

6、线程比较

对于线程ID比较,为了可移植操作,不能简单地把线程ID当作整数来处理,因为不同系统对线程ID的定义可能不一样。应该要下边的函数:

函数原型:

int pthread_equal(pthread_t tid1, pthread_t tid2);

返回值: 若相等则返回非0值,否则返回0

tid1,tid2:线程名字

示例代码

当线程退出值为整数时

#include <stdio.h>
#include <pthread.h>
void *func(void *arg)
{
    static int ret = 10; //定义变量,注意为static类型
    printf("t1 id = %ld thread is create\n",(unsigned long)pthread_self());//打印t1线程id
    printf("t1 param is %d\n",*((int *)arg));  //将main线程传递的数据打印出来
    pthread_exit((void *)&ret);  //线程退出,10为退出码
}
int main()
{
    int ret;
    int param = 100;
    int *pret = NULL;
    pthread_t t1; //创建t1线程
    ret = pthread_create(&t1,NULL,func,(void *)&param);//如果有多个数据时,建立一个结构体param
    if(ret == 0){
        printf("main create t1 success\n");
    }
    printf("main = %ld\n",(unsigned long)pthread_self()); //打印main线程id
//      sleep(5);   //等待线程执行完
//      pthread_join(t1,NULL); //等待线程退出,不收集退出信息
     pthread_join(t1,(void **)&pret);  //将退出信息放入到指针pret中
     printf("main t1 quit is %d\n",*pret); //打印退出信息
     return 0;
}

运行结果
在这里插入图片描述
当线程退出值为字符串时

#include <stdio.h>
#include <pthread.h>
void *func(void *arg)
{
    static char *pret = "hello world";//定义变量,注意为static类型
    printf("t1 id = %ld thread is create\n",(unsigned long)pthread_self());//打印t1线程id
    printf("t1 param is %d\n",*((int *)arg));  //将main线程传递的数据打印出来
    pthread_exit((void *)pret);  //线程退出,10为退出码
}
int main()
{
    int ret;
    int param = 100;
    char *pret = NULL;
    pthread_t t1; //创建t1线程
    ret = pthread_create(&t1,NULL,func,(void *)&param);//如果有多个数据时,建立一个结构体param
    if(ret == 0){
        printf("main create t1 success\n");
    }
    printf("main = %ld\n",(unsigned long)pthread_self()); //打印main线程id
//      sleep(5);   //等待线程执行完
//      pthread_join(t1,NULL); //等待线程退出,不收集退出信息
     pthread_join(t1,(void **)&pret);  //将退出信息放入到指针pret中
     printf("main t1 quit is %s\n",pret); //打印退出信息
     return 0;
}

运行结果
在这里插入图片描述

线程共享内存的验证

#include <stdio.h>
#include <pthread.h>
int p_data = 0;
void *func1(void *arg)
{
    printf("t1 param is %d\n",*((int *)arg));//main传递的数据
    while(1){
        printf("t1 p_data : %d\n",p_data++);//打印全局变量p_data
        sleep(1);        //睡眠1s
    }
}
void *func2(void *arg)
{
    printf("t2 param is %d\n",*((int *)arg));//main函数传递的值
    while(1){
        printf("t2 p_data : %d\n",p_data++); //打印全局变量
        sleep(1);              //睡眠1s
    }
}
int main()
{
    int ret;
    int param = 100; //传递的数据
    pthread_t t1;    //线程一
    pthread_t t2;    //线程二
    ret = pthread_create(&t1,NULL,func1,(void *)&param); //创建线程一
    if(ret == 0){
    	printf("main create t1 success\n");
    }
    ret = pthread_create(&t2,NULL,func2,(void *)&param); //创建线程二
    if(ret == 0){
        printf("main create t2 success\n");
    }
    while(1){
        printf("main p_data : %d\n",p_data++); //全局变量在main函数中的值
        sleep(1);
    }
    pthread_join(t1,NULL);       //等待线程一退出
    pthread_join(t2,NULL);       //等待线程二退出
    return 0;
}

运行结果
在这里插入图片描述
可以看到 p_data 在任意一个线程中改变值,都会影响其他线程 p_data 的值,也就是同一进程下的线程的内存是共享的。