【Linux线程】Linux线程编程基础:概念、创建与管理-????3. 线程控制

POSIX线程库定义了一套用于创建、操纵和管理线程的API。这些API允许程序员在Unix-like系统(如Linux、Solaris)上编写多线程程序

  • 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”打头的
  • 要使用这些函数库,要通过引入头文件<pthread.h>
  • 链接这些线程函数库时要使用编译器命令的“-lpthread”选项

如何查看线程:

指令:ps -aL

在这里插入图片描述


????创建线程

pthread_create:

在这里插入图片描述

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

参数说明:

  • thread:返回线程ID
  • attr:设置线程的属性,attr为NULL表示使用默认属性
  • start_routine:是个函数地址,线程启动后要执行的函数
  • arg:传递给线程函数的参数,可以是任何类型的数据,但需要通过类型转换与线程函数中的参数类型匹配,也可以传一个类

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

代码示例:

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

void *ThreadRoutine(void *args)
{
    string threadname = static_cast<const char*>(args);
    while(1)
    {
        cout << "new thread" << ", thread name: " << threadname << endl;
        sleep(1);
    }
    
}

int main()
{
    pthread_t tid;

    ThreadData *td = new ThreadData("thread_1", (uint64_t)time(nullptr), Print);

    pthread_create(&tid, nullptr, ThreadRountine, td);
    
    while(1)
    {
        cout << "I am a main thread" << endl;
        sleep(1);
    }
    return 0;
}

????线程终止

在多线程编程中,线程终止(Thread Termination)是指一个线程结束其执行过程,释放相关资源,并退出其生命周期。线程终止可以是由于线程正常完成其任务,也可以是由于某些异常情况或外部请求导致的提前结束

只终止某个线程而不终止整个进程:

  • 从线程函数return。这种方法对主线程不适用,从main函数return相当于调用exit
  • 线程可以调用pthread_ exit终止自己
  • 一个线程可以调用pthread_ cancel终止同一进程中的另一个线程

pthread_exit:

在这里插入图片描述

代码示例:(运行5秒后退出)

void *ThreadRoutine(void *args)
{
    string threadname = static_cast<const char*>(args);

    int cnt = 5;
    while(cnt--)
    {
        cout << "new thread -> name: " << threadname << endl;
        sleep(1);
    }

    // return nullptr;
    pthread_exit(nullptr);
}

在这里插入图片描述


pthread_cancel:

在这里插入图片描述

int pthread_cancel(pthread_t thread);

参数:

  • thread:线程ID

代码示例:

void *ThreadRoutine(void *args)
{
    string threadname = static_cast<const char*>(args);

    int cnt = 5;
    while(cnt--)
    {
        cout << "new thread -> name: " << threadname << endl;
        sleep(1);
    }

    cout << "other thread cancel done" << endl;
    
    return nullptr;
}

int main()
{
    pthread_t tid;

    pthread_create(&tid, nullptr, ThreadRoutine, (void *)"thread_1");

    sleep(5);
    // pthread_detach(tid);
    int n = pthread_cancel(tid);
    cout << "main thread done" << ", n: " << n << endl;

    void *ret = nullptr;

    n = pthread_join(tid, &ret);
    cout << "main thread join done" << " n: " << n << ", thread return: " << (int64_t)ret << endl;
    
    return 0;
}

在这里插入图片描述

线程如果是被分离的,该线程可以被取消,但是不能被等待


????线程等待

在Linux或多线程编程环境中,线程等待通常指的是一个线程暂停其执行,直到满足某个特定条件或另一个线程完成某个任务后再继续执行

pthread_join:

在这里插入图片描述

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

参数:

  • thread:线程ID
  • value_ptr:它指向一个指针,后者指向线程的返回值

代码示例:

void *ThreadRoutine(void *args)
{
    string threadname = static_cast<const char*>(args);

    int cnt = 5;
    while(cnt--)
    {
        cout << "new thread -> name: " << threadname << endl;
        sleep(1);
    }

    cout << "other thread done" << endl;
    // return nullptr;
    pthread_exit(nullptr);
}

int main()
{
    pthread_t tid;

    pthread_create(&tid, nullptr, ThreadRoutine, (void *)"thread_1");

    sleep(10);
    int n = pthread_join(tid, nullptr);
    cout << "main thread done" << " n: " << n << endl;

    sleep(5);

    return 0;

}

在这里插入图片描述

如果我们想获取线程的返回值,我们要注意pthread_join的第二个参数是void **类型,而ThreadRoutine的返回值为void *,因此我们要对格外注意

获取线程的返回值:

void *ThreadRoutine(void *args)
{
    string threadname = static_cast<const char*>(args);

    int cnt = 5;
    while(cnt--)
    {
        cout << "new thread -> name: " << threadname << endl;
        sleep(1);
    }

    cout << "other thread done" << endl;
    // return nullptr;
    return (void *)"thread_1 done";
}

int main()
{
    pthread_t tid;

    pthread_create(&tid, nullptr, ThreadRoutine, (void *)"thread_1");
	
	void *ret = nullptr;	

    int n = pthread_join(tid, &ret); // 注意这里要&ret	
    cout << "main thread done" << " n: " << n << "thread done and return: "<< (const char*)ret << endl;

    return 0;

}

在这里插入图片描述


????线程分离

分离线程是多线程编程中的一个重要概念,它指的是将一个线程从主线程或创建它的线程中分离出来,使其能够独立运行,并且不再需要其他线程使用特定的函数(如pthread_join())来等待其结束

pthread_detach:

在这里插入图片描述

int pthread_detach(pthread_t thread);

参数:

  • thread 是你想要分离的线程的标识符(线程ID)

返回值:如果成功,pthread_detach 返回 0。如果失败,它返回一个错误码


代码示例:(在线程分离后等待线程)

// 线程分离
void *ThreadRoutine(void *args)
{
    string threadname = static_cast<const char*>(args);

    int cnt = 5;
    while(cnt--)
    {
        cout << "new thread -> name: " << threadname << endl;
        sleep(1);
    }

    cout << "other thread done" << endl;
    
    return nullptr;
}

int main()
{
    pthread_t tid;

    pthread_create(&tid, nullptr, ThreadRoutine, (void *)"thread_1");

    sleep(1);
    pthread_detach(tid);

    int n = pthread_join(tid, nullptr);
    cout << "main thread done" << " n: " << n << endl;
    
    return 0;
}

在这里插入图片描述

在线程分离后等待线程,线程会直接返回一个错误码


????线程ID

线程ID本质是一个地址

void *ThreadRoutine(void *args)
{
    string threadname = static_cast<const char*>(args);

    while(1)
    {
        cout << "new thread -> name: " << threadname << endl;
        sleep(1);
    }
}

int main()
{
    pthread_t tid;

    pthread_create(&tid, nullptr, ThreadRoutine, (void *)"thread_1");

    cout << "tid: " << tid << endl;
    
    while(1)
    {
        cout << "I am a main thread" << endl;
        sleep(1);
    }
    return 0;

}

在这里插入图片描述


pthread_self:

功能:可以获得线程自身的ID

在这里插入图片描述

pthread_t pthread_self(void);

返回值:pthread_self 函数返回一个类型为 pthread_t 的值,这个值唯一地标识了调用它的线程。pthread_t 通常是一个整数或结构体,用于表示线程标识符

代码示例:

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, ThreadRoutine, (void *)"thread_1");

    cout << "pthread_t id: " << pthread_self() << endl;

    return 0;
}

在这里插入图片描述
线程库要想管理线程,那么它必须要先被加载到地址空间中的mmap区域,线程库是共享的,内部要管理整个系统的,多个用户启动的所有线程

对于Linux目前实现的NPTL实现而言,pthread_t类型的线程ID,本质就是一个进程地址空间上的一个地址,为了方便我们的库直接找到内存,而pthread_t ID就是pthread的首地址,pthread库要自己维护线程这块栈区

在这里插入图片描述

  • 线程可以通过函数fork来创建子进程,但是线程不能进行进程程序替换,因为线程是共用主线程的资源,一旦一个线程进行进程程序替换后,所有的线程包括主线程的代码都会被替换为别的程序

上一篇:深度学习实战95-跨框架应用中onnx的作用,pytorch模型转onnx的实战


下一篇:用你的手机/电脑运行文生图方案