【Linux】详解线程控制之线程创建&线程终止&线程等待&线程分离

一、线程创建

thread:这是一个指向pthread_t类型的指针,用于获取新创建线程的线程ID。在调用pthread_create后,这个指针会被设置为新线程的ID。

attr:这是一个指向pthread_attr_t类型的指针,用于设置线程的属性,如栈大小、优先级等。如果这个参数为NULL,那么线程将使用默认的属性。通常情况下,如果你不需要设置特殊的线程属性,可以传递NULL。

 

start_routine:这是一个函数指针,指向线程开始执行时要调用的函数。这个函数通常被称为线程的“入口点”或“启动例程”。

arg:用于向线程的启动例程传递参数。你可以通过这个参数向线程传递任何类型的数据。如果你的启动例程不需要任何参数,可以传递NULL。

二、线程终止

终止线程的三种方法:

  1. 在线程函数的内部使用return语句。
  2. 在线程函数的内部使用pthread_exit函数。
  3. 在主线程中使用pthread_cancel函数,可以回收指定的子线程。

2.1、pthread_exit函数

         pthread_exit函数中可以设置retval返回值,在主线程中可以调用pthread_join函数来获取子线程的返回值

2.2、pthread_cancel函数

        在主线程中使用pthread_cancel函数,在pthread_cancel函数中传入子进程的id可以直接终止子线程,不用等子线程跑完

2.3、注意点

不能用exit终止线程,因为exit是用来终止进程的,一旦exit执行了,那么整个进程也就退出了

三、线程等待回收

线程也要被等待回收,不然会出现类似于进程等待那里的僵尸问题,也就是出现内存泄漏。

        pthread_join函数可以用来回收子线程,第一个参数为子线程的id, 第二个参数可以得到子线程的退出信息。主线程退出整个进程就跟着退出了,也就意味着主线程退出所有线程都要跟着退出,所以我们一般需要主线程最后退出来等待回收子线程

四、线程创建、终止、回收的例子

        下面由主线程创建一批子线程,分配给子线程任务,子线程将结果封装起来并返回给主线程,主线程由此可以获取子线程的执行结果。

对任务进行封装,让子线程去执行加法任务:

class Task
{
private:
    int _x;
    int _y;
public:
    Task(int x, int y)
    :_x(x), _y(y)
    {}

    int Add()
    {
        return _x + _y;
    }
    ~Task()
    {}
};

分配给子线程任务,并回收结果:

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
using namespace std;

class ThreadData
{
private:
    Task _t;
    string _name;
public:
    ThreadData(Task t, string name)
    :_t(t), _name(name)
    {}

    Task getTask()
    {
        return _t;
    }

    string getName()
    {
        return _name;
    }
    ~ThreadData()
    {}
};
//结果封装
class Res
{
private:
    int _result;
    string _name;
public:
    Res(int result, string name)
    :_result(result)
    ,_name(name)
    {}

    int getResult()
    {
        return _result;
    }

    string getName()
    {
        return _name;
    }
    ~Res()
    {}
};
//子线程执行的函数
void* handler(void* args)
{
    ThreadData* th = (ThreadData*)args;
    Res* res = new Res(th->getTask().Add(), th->getName());
    delete th;
    return res;
}

vector<pthread_t> vect_tid;
vector<Res*> vect_res;
int main()
{
    for(int i = 0; i<5; i++)
    {
        pthread_t tid;
        Task task(10, 20);
        char buffer[1024];
        snprintf(buffer, sizeof(buffer), "thread-%d", i+1);
        ThreadData* th = new ThreadData(task, buffer);
        pthread_create(&tid, nullptr, handler, th);
        vect_tid.push_back(tid);
    }

    for(auto& e : vect_tid)
    {
        void* ret = nullptr;
        pthread_join(e, &ret);
        vect_res.push_back((Res*)(ret));
    }

    for(auto& e : vect_res)
    {
        cout << e->getName() << " " << "res=" << e->getResult() << endl;
        delete e;
    }
    return 0;
}

五、线程分离

        线程被创建出来的时候默认是joinable的,也就是说需要被等待的。如果我们的主线程并不关心新线程的执行结果,我们可以将新线程设置为分离状态。所谓的分离只是进程的一种工作状态,在底层依旧数据共享,依旧属于同一个进程

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

void* handler(void* args)
{
    const std::string str = static_cast<const char*> (args);
    int cnt = 5;
    while(cnt--)
    {
        std::cout << str << std::endl;
        sleep(1);
    }

    return nullptr;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, handler, (void*)"new Thread");
    //detach可以放在main函数中也可以放在handler函数中
    pthread_detach(tid);
    while(true)
    {}
    return 0;
}

        分离之后再主线程中就不需要再对子线程进行等待回收了,即不需要在主线程中调用pthread_join函数。

  • 99
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 72
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 72
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北飞的山羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值