【Linux】线程控制

接口

pthread_create()线程创建

  • pthread_t* thread:输出型参数,将线程的tid值放入到我们外部创建好的pthread_t 类型的变量中。
  • const pthread_attr_t *attr:用来设置线程属性,一般情况下设置成nullptr,等用到的时候再详细讲解。
  • void* (*start_routine)(void *):函数指针,这是一个回调函数,该函数的内容就是新线程要执行的
  • void* arg:回到函数的参数。
  • 返回值: 线程创建成功返回0,不成功返回错误码。
#include<iostream>
#include<unistd.h>
#include<pthread.h>

using namespace std;

#define NUM 10

void* test(void* args)
{
    sleep(1);
    string name = (char*) (args);
    while(1)
    {
        cout << "new thread name:" << name << endl;
        sleep(1);
    }
}
int main()
{
    
    for (int i = 0; i < NUM; i ++)
    {
        pthread_t tid;
        char buffer[64];
        snprintf(buffer, sizeof buffer, "thread %d", i+1);
        pthread_create(&tid, nullptr, test, (void*)buffer);
    }

    while(1)
    {
        cout << "create success..." << endl; 
        sleep(1);
    }

    return 0;
}

运行结果如下: 

为什么会导致这样的结果?

观察上面主线程创建子线程的时候,我们在for循环里定义了buffer缓冲区,然后将线程的名字打印进buffer中。

理想的结果是打印thread 1, thread 2, thread3...但是结果是只打印了thread10。

原因:

1、buffer的生命周期在for循环内部,当跳出循环的时候buffer就消失了,新创建的buffer会继续在上一个buffer的地址位置创建新的buffer。

2、因为buffer生命周期的原因,并且pthread_create传递的是buffer的地址,所以,其实所有的线程拿到的是同一个缓冲区。pthead 1,phtead2等等会被后面的线程覆盖,最后都变成pthread10。

所以,为了让所有的线程都有自己的缓冲区,可以new一个空间给每个空间。避免了生命周期的问题。

1、解决方法一 

2、解决方法二

 使用类,将内容写入到每个线程的类中。

执行结果:

pthread_exit()结束线程

 

  • 参数:返回线程结束信息,当前阶段设置成nullptr即可。

执行结果:

pthread_join()线程等待函数

和进程等待一样,将线程回收,避免内存泄漏

  • pthread_t thread:要等待的线程tid。
  • void** retval:线程结束信息返回,这是一个输出型参数。
  • 返回值:等待成功返回0,等待失败返回错误码。

运行结果:

线程等待返回值

运行结果:

所以,可以通过线程等待的返回值判断线程是不是正常退出

 pthread_canel()取消线程

 

pthread_self()查看线程tid

查看线程自己的tid,和查看进程的pid一样,接口是pthread_join

作用就是查看调用该函数的线程的tid

pthead_detach()线程分离

从上面的各种结果可以看出,线程等待是阻塞等待

按道理说,应该是主线程边打印,子线程边进行。但是程序执行的结果表示,子线程执行完了再执行主线程的内容。

当主线程不关注子线程的退出情况的时候,阻塞等待就现得很没用。所以,我们可不可以不进行阻塞等待呢?

可以。

返回值:成功返回0,失败返回错误码

一个线程不能既是joinable,又是分离的。将线程设置为分离的之后,主线程将不再关心线程的退出状态,子线程会自动释放

线程分离之后再进行线程等待会失败

void* test(void* args)
{
    sleep(1);
    char *name = (char*)args;
    //进行线程分离
    pthread_detach(pthread_self());
    int cnt = 5;
    while(cnt--)
    {
        cout << "new thread name:" << name << endl;
        sleep(1);
    }

    return (void*) 1;
}
int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, test, (void *)"thread one");
    int n = pthread_join(tid, nullptr);
    cout << "join pthread -> " << strerror(n) << endl;
    return 0;
}

执行结果:

线程等待成功

不是说线程分离了再进行线程等待就会失败吗?怎么上面的运行结果仍然是等待成功呢

因为主线程先被调度,在新线程被创建但是没有执行的时候主线程就开始等待新线程了。

所以当新线程将自己分离以后,主线程已经处于等待状态了,它不认为新线程被分离,还会继续等待,而且可以等待成功。

如果让主线程先等待一会儿,让新线程先执行,就可以看到线程等待失败

执行结果:

正确的做法:在主线程中分离新线程

void* test(void* args)
{
    sleep(1);
    char *name = (char*)args;
    int cnt = 5;
    while(cnt--)
    {
        cout << "new thread name:" << name << endl;
        sleep(1);
    }

    return (void*) 1;
}
int main()
{
    pthread_t tid;
    cout << "主线程tid: " << pthread_self() << endl;
    
    pthread_create(&tid, nullptr, test, (void *)"thread one");
    pthread_detach(tid);
    int n = pthread_join(tid, nullptr);
    cout << "join pthread -> " << strerror(n) << endl;

    while(1)
    {
        cout << "主线程..." << endl;
        sleep(1);
    }

    return 0;
}

这样做的好处是,在主线程等待失败之后,主线程并不会阻塞。从后来一直打印"主线程..."这里可以看出来。

 

  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值