【Linux】线程控制

接口

pthread_create()线程创建

  • pthread_t* thread:输出型参数,将线程的tid值放入到我们外部创建好的pthread_t 类型的变量中。
  • const pthread_attr_t *attr:用来设置线程属性,一般情况下设置成nullptr,等用到的时候再详细讲解。
  • void* (*start_routine)(void *):函数指针,这是一个回调函数,该函数的内容就是新线程要执行的
  • void* arg:回到函数的参数。
  • 返回值: 线程创建成功返回0,不成功返回错误码。
cpp 复制代码
#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,又是分离的**。将线程设置为分离的之后,主线程将不再关心线程的退出状态,子线程会自动释放**。

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

cpp 复制代码
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;
}

执行结果:

线程等待成功

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

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

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

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

执行结果:

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

cpp 复制代码
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;
}

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

相关推荐
独正己身8 分钟前
代码随想录day3
数据结构·c++·算法
Hunter_pcx9 分钟前
[C++技能提升]类注册
c++·人工智能
半夏知半秋20 分钟前
rust学习-rust中的格式化打印
服务器·开发语言·后端·学习·rust
mcharleylei21 分钟前
Centos 安装docker
linux·docker·centos
IU宝1 小时前
vector的使用,以及部分功能的模拟实现(C++)
开发语言·c++
小熊科研路(同名GZH)1 小时前
【Matlab高端绘图SCI绘图模板】第05期 绘制高阶折线图
开发语言·matlab·信息可视化
&白帝&1 小时前
JAVA JDK7时间相关类
java·开发语言·python
geovindu1 小时前
Qt Designer and Python: Build Your GUI
开发语言·qt
Xiao Xiangζั͡ޓއއ1 小时前
程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图<1>
c语言·开发语言·程序人生·学习方法·改行学it
狄加山6751 小时前
系统编程(线程互斥)
java·开发语言