Linux应用开发 - 多线程编程

Linux应用开发 - 多线程编程

定义

线程是进程中的一个独立的代码块。说白了,其实它就是个函数,只不过再也不用像以前的函数调用来调用它。而是通过pthread_create函数来创建它,也就是告诉内核,这个函数是个线程,今后交给你来调度了。

相关API

//创建线程 
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); 
//退出线程 
void pthread_exit(void *retval); 
//回收线程 
int pthread_join(pthread_t thread, void **retval); 
//分离线程 
int pthread_detach(pthread_t thread); 
//取消线程 
int pthread_cancel(pthread_t thread); 
//获取本线程的ID 
pthread_t pthread_self(void); 
//判断两个线程id是否相等 
int pthread_equal(pthread_t t1, pthread_t t2);

案例1

创建线程

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

void *fun(void *arge)
{
    printf("pthread new = %lu\n",(unsigned int)pthread_self());
}

int main(void)
{
    pthread_t tid1;
    int ret = pthread_create(&tid1,NULL,fun,NULL);
    if (ret!=0)
    {
        perror("pthread error\n");
        return -1;
        /* code */
    }
    printf("tid_main=%lu tid_new=%lu\n",(unsigned int)pthread_self(),tid1); // tid1标识线程创建成功后指向的空间
    sleep(1);//为了等会儿子线程 要不主线程一执行完就结束了
    
    return 0;
}

这个案例仅是用于在主进程中创建一个线程

线程函数的程序在 pthread 库中,故链接时要加上参数 -lpthread。

运行结果:

tid_main=1999865600 tid_new=140696530216704
pthread new = 1991534336

函数说明:

int pthread_create( pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void ( func) (void *), void *restrict arg )

  • thread:线程标识符
  • attr: 线程属性设置 null表示采用默认
  • start_roitine : 线程函数的启示地址、
  • arg :传递给start_routine的参数
  • 返回值:成功:0出错:-1

案例2

线程传参

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

struct student
{
    int age;
    char name[20];
    /* data */
};


void *fun(void *stu)
{
    printf("pthread new = %lu\n",(unsigned int)pthread_self());
    printf("name:%s\tage:%d\n",((struct student *)stu)->name,((struct student *)stu)->age);
}

int main(void)
{
    struct student stu;
    stu.age = 10;
    memcpy(stu.name,"liming",6);

    pthread_t tid1;
    int ret = pthread_create(&tid1,NULL,fun,(void *)&stu);
    if (ret!=0)
    {
        perror("pthread error\n");
        return -1;
        /* code */
    }
    printf("tid_main=%lu tid_new=%lu\n",(unsigned int)pthread_self(),tid1); // tid1标识线程创建成功后指向的空间
    sleep(1);//为了等会儿子线程 要不主线程一执行完就结束了
    
    return 0;
}

运行结果:

tid_main=3901490944 tid_new=140084251518720
pthread new = 3893159680
name:liming age:10

案例3

线程退出

终止线程执行(3种方法)

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <error.h>
#include <string.h>
#include <stdlib.h>
void *thread_fun(void *args)
{
    if (strcmp("1", (char *)args) == 0)
    {
        printf("new thread return\n");
        return (void *)1;
        /* code */
    }
    if (strcmp("2", (char *)args) == 0)
    {
        printf("new thread pthread_exit\n");
        pthread_exit((void *)2);
        /* code */
    }
    if (strcmp("3", (char *)args) == 0)
    {
        printf("new thread exit\n");
        exit(3);
    }
}

int main(int argc, char *argv[])
{
    int err;
    pthread_t tid;
    err = pthread_create(&tid, NULL, thread_fun, (void *)argv[1]);
    if (err != 0)
    {
        printf("creat thread fail\n");
        return 0;
    }
    sleep(1);
    printf("main func\n");
    return 0;
}

运行结果:

./exit1 1

new thread return
main func

return的作用是:返回到调用者处。有可能会退出进程(放在主线程时),有可能会退出线程,也有可能什么也不退出。

./exit1 2

new thread pthread_exit
main func

只退出当前子线程。注意:在主线程退出时,其它线程不会结束。同样可以执行。所以这个只字非常重要。并且,与return一样,pthread_exit退出的线程也需要调用pthread_join去回收子线程的资源(8k左右),否则服务器长时间运行会浪费资源导致无法再创建新线程。

./exit1 3

new thread exit

将进程退出,无论哪个子线程调用整个程序都将结束。

案例4

线程回收

#include <stdio.h>
#include <pthread.h>
//定义线程要执行的函数,arg 为接收线程传递过来的数据
void* Thread1(void* arg)
{
    printf("hello linux\n");
    return "Thread1成功执行";
}
//定义线程要执行的函数,arg 为接收线程传递过来的数据
void* Thread2(void* arg)
{
    printf("李魁\n");
    return "Thread2成功执行";
}

int main()
{
    int res;
    //创建两个线程变量 
    pthread_t mythread1, mythread2;
    void* thread_result;
    //创建 mythread1 线程,执行 Thread1() 函数
    res = pthread_create(&mythread1, NULL, Thread1, NULL);
    if (res != 0) {
        printf("线程创建失败");
        return 0;
    }
    //创建 mythread2 线程,执行 Thread2() 函数
    res = pthread_create(&mythread2, NULL, Thread2, NULL);
    if (res != 0) {
        printf("线程创建失败");
        return 0;
    }
    //阻塞主线程,直至 mythread1 线程执行结束,用 thread_result 指向接收到的返回值,阻塞状态才消除。
    res = pthread_join(mythread1, &thread_result);
    //输出线程执行完毕后返回的数据
    printf("%s\n", (char*)thread_result);
    //阻塞主线程,直至 mythread2 线程执行结束,用 thread_result 指向接收到的返回值,阻塞状态才消除。
    res = pthread_join(mythread2, &thread_result);
    printf("%s\n", (char*)thread_result);
    printf("主线程执行完毕");
    return 0;
}

运行结果:

hello linux
李魁
Thread1成功执行
Thread2成功执行
主线程执行完毕

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

函数功能:

  • 接收目标线程执行结束时的返回值
  • 释放目标线程占用的进程资源

thread 参数用于指定目标线程;retval 参数用于存储接收到的返回值。实际场景中,调用 pthread_join() 函数可能仅是为了及时释放目标线程占用的资源,并不想接收它的返回值,这种情况下可以将 retval 置为 NULL。

函数会一直阻塞当前线程,直至目标线程执行结束,阻塞状态才会消除。如果成功等到了目标线程执行结束(成功获取到目标线程的返回值)函数返回数字 0,否则返回非零数。

  • 程序中共有 3 个线程,分别是主线程,mythread1 线程和 mythread2 线程。mythread1 线程负责执行 Thread1() 函数,mythread2 线程负责执行 Thread2() 函数。
  • 主线程先后调用了两次 pthread_join() 函数,都会阻塞主线程,直至 mythread1 和 mythread2 线程执行完毕,阻塞状态才会消除。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值