Linux多线程编程一(系统编程)

线程控制

创建线程

int pthread_create(pthread_t *thread,const pthread_attr_t *attr, \
    void*(*start_routine)(void*),void *arg);

第一个参数:返回线程id
第二个参数:设置线程属性默认NULL
第三个参数:函数地址,线程启动后执行的函数
第四个参数:传给线程启动函数的参数
成功:返回0 失败:返回错误码

#include
#include
#include
#include
#include

void *rout(void *_val)
{
        printf("I am %s pid is : %d , tid is : %u\n",(char*)_val,(int)getpid(),(unsigned long long)pthread_self());
        return NULL;
}
int main()
{
    pthread_t tid;
    int ret;
    ret=pthread_create(&tid,NULL,rout,"pthread1");
    if(ret!=0)
    {
        fprintf(stderr, "pthread_create: %s\n",strerror(ret));
        exit(EXIT_FAILURE);
    }
        printf("I am main thread pid is : %d , tid is %u\n",(int)getpid(),(unsigned long long)pthread_self());
        sleep(1);
        return 0;
}

Linux多线程编程一(系统编程)_第1张图片
由上例可以看出pthread_t 类型是一个地址值
属于同一进程的多个线程调用getpid()可以得到相同的进程号
调用pthread_self()得到的线程号各不相同。

线程终止

#include 
void pthread_exit(void *retval);

pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用malloc分配,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了。

取消线程

#include 
int pthread_cancel(pthread_t thread);

线程是允许被取消的,退出结果为-1,线程自己取消自己(不推荐)退出结果为0。
线程等待
为什么要线程等待?
main函数执行的线程称为主线程,多线程的执行顺序由线程调度决定
主线程必须回收其他线程,否则就会产生类似僵尸进程的状况(内存泄漏)。

#include 
int pthread_join(pthread_t thread, void **retval);

返回值:成功返回0,失败返回错误码。
参数thread:线程号,即要等待线程的tid
参数retval:要等待线程的退出码(输出型参数)

举例

#include
#include
#include
#include
#include


void *thread1(void *val1)
{
    printf("thread 1 returning .....\n");
    printf("%s:pid is %d,tid is %u\n",(char*)val1,getpid(),pthread_self());
    return (void*)0; //线程终止方式1,用return返回
}

void *thread2(void *val2)
{
    printf("thread 2 exiting .....\n");
    printf("%s:pid is %d,tid is %u\n",(char*)val2,getpid(),pthread_self());
    pthread_exit ((void*)2);//线程终止方式2,调用pthread_exit
}

void *thread3(void *val3)
{
    printf("%s:pid is %d,tid is %u\n",(char*)val3,getpid(),pthread_self());
    while(1)
    {
        printf("thread 3 is running....\n");
        sleep(1);
    }
                    //线程终止方式3,用pthread_exit退i出
}


int main()
{
    pthread_t tid1; 
    pthread_t tid2;
    pthread_t tid3;
    void *ret;

    //thread 1 return 
    pthread_create(&tid1,NULL,thread1,"thread1"); //线程1创建
    pthread_join(tid1,&ret);                 //wait 线程1  ret指向单元存放thread1的返回值
    printf("thread1 return return code:%d\n",(int)ret);


    //thread 2 exit
    pthread_create(&tid2,NULL,thread2,"thread2"); //线程2创建
    pthread_join(tid2,&ret);                 //wait线程2  ret指向单元存放传给pthread_exit的参数
    printf("thread exit, exit code:%d\n",(int)ret);


    //thread 3 pthread_cancel
    pthread_create(&tid3,NULL,thread3,"thread3"); //线程3创建
    sleep(3);
    pthread_cancel(tid3);                 //线程3被其他线程用pthread_cancel取消了
    pthread_join(tid3,&ret);              //wait 线程3  ret指向单元存放PTHREAD_CANCELED
    if(ret==PTHREAD_CANCELED)
    {
        printf("thread  3 cancel ,cancel code id %d\n",(int)ret);
    }
    printf("main thread run: pid is %d , tid is %u\n", getpid(),pthread_self());
    return 0;

}

Linux多线程编程一(系统编程)_第2张图片
通过上图可以发现为什么3个线程的pid和tid都是相同的呢?
是pid实际上是主线程的进程号
线程号的线程的唯一标识符,为什么不同的线程,线程号是相同的?
调用过线程等待函数之后主线程就会回收其资源,其中当然也包括线程id,,当线程1回收之后,我们紧接着创建了线程2,系统会优先选择刚刚回收的1号线程id来分配给线程2,当线程2终止等待之后,此线程号再次被回收利用,进而分配给线程3,这就是为什么我们看到不同的3个线程拥有同一个tid了。

线程的属性

线程的两种属性:可结合性可分离性

默认线程的创建是可结合的
一个分离的线程是不能被其他线程回收或杀死的,它的存 储器 资源在它终止时由系统自动释放。

由于调用pthread_join后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此。改善方法:
1>可以在子线程中加入代码:

pthread_detach(pthread_self())

2>父线程调用

pthread_detach(thread_id)(非阻塞,可立即返回)

这将该子线程的状态设置为分离的(detached),detached),如一来,该线程运行结束后会自动释放所有资源。

#include
#include
#include
#include
#include

void *thread_run(void* arg)
{
    pthread_detach(pthread_self());
    printf("%s\n",(char*)arg);
    return NULL;
}

int main(void)
{
    pthread_t tid;
    if(pthread_create(&tid,NULL,thread_run, "thread1 run...")!=0)
    {
        printf("create thread error\n");
        return 1;
    }
    int ret=0;
    sleep(1);

    if(pthread_join(tid,NULL)==0)
    {
        printf("pthread wait success!\n");
        ret=0;
    }
    else
    {
        printf("pthread wait failed\n");
        ret=1;
    }
    return ret;
}

Linux多线程编程一(系统编程)_第3张图片
线程启动时执行程序thread_run函数进行线程分离,主线程sleep1秒,然后主线程执行等待函数,因为线程已经被分离了,等待函数无法对其资金进行回收,所有等待失败。

你可能感兴趣的:(Linux)