Linux 线程Pthread(一)创建、终止、获取TID

本文详细介绍了Linux环境下的线程机制,包括线程标识、创建和终止。线程ID用于区分同一进程中的线程,创建线程时需要指定回调函数和参数。线程的终止可能导致进程结束,使用pthread_exit可以控制线程的退出状态。需要注意,返回值不能是栈上的变量,以防止线程返回后被覆盖。

多线程一直接触,这次系统学习一蛤。

多线程目的是在单进程环境下执行多个任务。一个进程中的所有线程都可以访问该进程的组成部件,如文件描述符和内存。

单个资源在多个用户间共享,就必须处理一致性问题。

同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。

但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。

通过__thread关键字是GCC内置的线程局部存储设施,存储效率堪比全局变量,它保证该变量在每个线程中都有独立的实体,互不干扰

1.线程标识

每个线程有一个线程ID,并且这个ID只有在它所属的进程上下文中才有意义。

#include <pthread.h>
pthread_t pthread_self(void);//获取当前线程的线程ID

#include <pthread.h>
int pthread_equal(pthread_t tid1,pthread_t tid2);
//相等返回非0
//否则返回0

pid_t用来标志进程,是一个非负整数,而pthread_t则有可能是一个结构体(取决于实现)。
因此,在调用pthread_equal的时候,参数必须严格是pthread_t类型的变量,否则将会出现未定义的行为:

The pthread_equal() function shall return a non-zero value if t1 and t2 are equal; otherwise, zero shall be returned.
If either t1 or t2 are not valid thread IDs, the behavior is undefined.

2.创建线程


#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

pthread_t * thread指向线程创建成功时线程id所在的内存单元
pthread_attr_t * attr创建时属性
start_routine即run in thread回调,这是一个函数指针,指向函数返回void* 参数是void*
void *arg即run in thread回调中的参数

3.线程终止 

如果进程中的任意线程调用了exit_Exit_exit函数,那么整个进程就会终止。
如果终止进程,则发送到线程的信号就会终止整个进程。

通过在线程中调用exit系列函数发现,确实主进程也随着退出,那么如何优雅地退出?

1.直接返回 return
2.被其他线程取消
3.线程自己调用pthread_exit

而通过pthread_join则可以知道return或者pthread_exit的状态码

#include <pthread.h>
void pthread_exit(void *retval);

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);

另外,在APUE中提到一个很重要的点,使用pthread_exit返回的变量不能是栈上变量,
我们知道每个线程有自己的栈,当某一个线程pthread_exit返回后,栈空间可能被另外的线程所覆盖

为了解决这个问题,我们可以使用全局变量和malloc函数分配的堆变量

下面这个代码测试了上述所有函数,详见github

//thread_exit.c

void *thread1(void *arg)
{
    pthread_t *tid1=(pthread_t*)(arg);

    int ret = pthread_equal(*tid1,pthread_self());

    printf("in thread1 tid = %lu, ret is %d\r\n",(unsigned long)pthread_self(),ret);


    return ((void*)2);
}

void *thread2(void *arg)
{
    pthread_t *tid1=(pthread_t*)(arg);

    int *a= (int *)malloc(sizeof(int));
    printf("in thread2 pointer %p\r\n",a);
    *a=5;
    int ret = pthread_equal(*tid1,pthread_self());
    printf("in thread2 tid = %lu,ret is %d\r\n",(unsigned long)pthread_self(),ret);
    pthread_exit((void*)a);
}


int main(void )
{
    pthread_t tid1;
    pthread_t tid2;

    int ret;
    ret = pthread_create(&tid1,NULL,thread1,&tid1);
    assert(ret==0);
    ret = pthread_create(&tid2,NULL,thread2,&tid1);//test
    assert(ret==0);

    printf("main thread:  %lu\r\n",(unsigned long)pthread_self());

    void * status;

    pthread_join(tid1,&status);
    printf("thread %lu exit status is %ld\r\n",(unsigned long)tid1,(long)status);



    int *fuck;
    pthread_join(tid2,(void*)&fuck);

    printf("======%d\r\n",*fuck);
    printf("in main pointer %p\r\n",fuck);
    free(fuck);//malloc in thread

    //printf("thread %lu exit status is %d\r\n",(unsigned long)tid2,*(int *)status);

    printf("main thread exit\r\n");

    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值