C++:pthread线程分离和线程属性

news/2025/2/26 0:50:17

在 C++ 的多线程编程中,pthread 库提供了强大的功能来管理线程。其中,线程分离和线程属性是两个重要的概念,它们对于优化线程的行为和资源管理有着关键作用。

线程分离

1.1 什么是线程分离

在 pthread 库中,线程有两种状态:可结合(joinable)和分离(detached)。默认情况下,新创建的线程是可结合的。可结合的线程在结束时,需要其他线程调用pthread_join函数来回收其资源,否则会造成资源泄漏。而分离的线程则会在结束时自动释放资源,无需其他线程来回收。

1.2 为什么要使用线程分离

在某些场景下,我们创建的线程执行完任务后,不需要获取其返回值,也不需要关心它的结束状态,此时将线程设置为分离状态可以避免资源浪费和不必要的同步开销。例如,在一个服务器程序中,为每个客户端连接创建一个线程来处理请求,这些线程处理完请求后就可以自动释放资源,不需要主线程逐个等待它们结束。

1.3 如何实现线程分离

在 pthread 库中,可以使用pthread_detach函数来将一个线程设置为分离状态。该函数的原型如下:

int pthread_detach(pthread_t thread);

thread是要设置为分离状态的线程标识符。
以下是一个简单的 C++ 代码示例,展示了如何创建一个分离的线程:

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

// 线程函数
void* thread_function(void* arg) {
    sleep(2);
    std::cout << "This is a detached thread." << std::endl;
    return nullptr;
}

int main() {
    pthread_t thread;
    // 创建线程
    if (pthread_create(&thread, nullptr, thread_function, nullptr)!= 0) {
        std::cerr << "Failed to create thread" << std::endl;
        return 1;
    }
    // 将线程设置为分离状态
    if (pthread_detach(thread)!= 0) {
        std::cerr << "Failed to detach thread" << std::endl;
        return 1;
    }
    std::cout << "Detached thread created successfully." << std::endl;
    // 主线程继续执行其他任务
    sleep(3);
    return 0;
}

创建了一个线程,并使用pthread_detach将其设置为分离状态。主线程在创建和分离线程后,继续执行其他任务,而分离的线程在完成任务后会自动释放资源,其他线程不能再使用 pthread_join 来等待它结束。
pthread_detach 可以在主函数调用,也可以在thread_function函数调用

#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;
int j = 2;
void* pthread_fun(void *arg)
{
    
    //自己设置为detached状态
    int ret = pthread_detach(pthread_self());
    while(j--)
    {
        cout << " in pthread_task" << endl;
        cout << *(int*)arg << endl;
        sleep(1);
    }
    // 线程返回一个整数值
    int* result = new int(42);
    return static_cast<void*>(result);//pthread_exit(reinterpret_cast<void*>(result));

}

int main()
{
    int ret = 0;
    pthread_t tid = 0;
    int argsend = 99;
    int i = 3;

    ret  = pthread_create(&tid, NULL, pthread_fun, &argsend);
    if(ret != 0)
    {
        cout << " pthread_create error" << endl;
        return -1;
    }
    while(i--)
    {
        cout << "pthread _create success" << endl;
        sleep(2);
    }
 
    
    return 0;
}

线程属性

2.1 线程属性概述

线程属性定义了线程的一些特性,如栈大小、调度策略、优先级等。通过设置线程属性,可以根据具体的应用需求来优化线程的行为。在 pthread 库中,使用pthread_attr_t类型来表示线程属性。

2.2 常见的线程属性

栈大小:线程的栈用于存储局部变量、函数调用信息等。可以通过pthread_attr_setstacksize函数来设置线程的栈大小。

pthread_attr_t attr;
pthread_attr_init(&attr);
size_t stack_size = 1024 * 1024; // 1MB栈大小
pthread_attr_setstacksize(&attr, stack_size);

调度策略:pthread 库支持多种调度策略,如 SCHED_OTHER(普通调度策略)、SCHED_FIFO(先进先出调度策略)、SCHED_RR(时间片轮转调度策略)。可以使用pthread_attr_setschedpolicy函数来设置调度策略。

pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_RR);

优先级:线程的优先级决定了它在 CPU 竞争中的优先级。可以通过pthread_attr_setschedparam函数来设置线程的优先级。

pthread_attr_t attr;
pthread_attr_init(&attr);
struct sched_param param;
param.sched_priority = 50; // 设置优先级
pthread_attr_setschedparam(&attr, &param);

2.3 使用线程属性创建线程

在创建线程时,可以将设置好的线程属性作为参数传递给pthread_create函数。

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

// 线程函数
void* thread_function(void* arg) {
    std::cout << "Thread is running." << std::endl;
    return nullptr;
}

int main() {
    pthread_t thread;
    pthread_attr_t attr;

    // 初始化线程属性
    pthread_attr_init(&attr);

    // 设置栈大小为2MB
    size_t stack_size = 2 * 1024 * 1024;
    pthread_attr_setstacksize(&attr, stack_size);

    // 设置调度策略为时间片轮转
    pthread_attr_setschedpolicy(&attr, SCHED_RR);

    // 设置优先级
    struct sched_param param;
    param.sched_priority = 50;
    pthread_attr_setschedparam(&attr, &param);

    // 使用设置好的属性创建线程
    if (pthread_create(&thread, &attr, thread_function, nullptr)!= 0) {
        std::cerr << "Failed to create thread" << std::endl;
        return 1;
    }

    // 等待线程结束
    if (pthread_join(thread, nullptr)!= 0) {
        std::cerr << "Failed to join thread" << std::endl;
        return 1;
    }

    // 销毁线程属性
    pthread_attr_destroy(&attr);

    return 0;
}

首先初始化了线程属性,然后设置了栈大小、调度策略和优先级,最后使用这些属性创建了一个线程

#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;
int j = 2;
void* pthread_fun(void *arg)
{
    
    //自己设置为detached状态
    //int ret = pthread_detach(pthread_self());
    while(j--)
    {
        cout << " in pthread_task" << endl;
        cout << *(int*)arg << endl;
        sleep(1);
    }
    // 线程返回一个整数值
    int* result = new int(42);
    return static_cast<void*>(result);//pthread_exit(reinterpret_cast<void*>(result));

}

int main()
{
    int ret = 0;
    pthread_t tid = 0;
    int argsend = 99;
    int i = 3;
    pthread_attr_t attr;
    // 初始化线程属性
    pthread_attr_init(&attr);

    ret  = pthread_create(&tid, NULL, pthread_fun, &argsend);
    if(ret != 0)
    {
        cout << " pthread_create error" << endl;
        return -1;
    }
    sched_param param;
    // 获取线程属性中的调度参数
    if (pthread_attr_getschedparam(&attr, &param) != 0) {
        std::cerr << "Failed to get scheduling parameters." << std::endl;
        return 1;
    }
    // 打印调度参数中的优先级
    std::cout << "Scheduling priority: " << param.sched_priority << std::endl;

    // 设置线程属性的分离状态为分离
    ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if (ret != 0) {
        cerr << "Failed to set detach state." << endl;
        return -1;
    }

    while(i--)
    {
        cout << "pthread _create success" << endl;
        sleep(2);
    }
    int detachstate;
    // 获取线程属性的分离状态
    if (pthread_attr_getdetachstate(&attr, &detachstate) != 0) {
        std::cerr << "Failed to get detach state." << std::endl;
        // 销毁线程属性对象
        pthread_attr_destroy(&attr);
        return 1;
    }

    // 根据分离状态输出相应信息
    if (detachstate == PTHREAD_CREATE_JOINABLE) {
        std::cout << "Thread is joinable." << std::endl;
    } else if (detachstate == PTHREAD_CREATE_DETACHED) {
        std::cout << "Thread is detached." << std::endl;
    } else {
        std::cout << "Unknown detach state." << std::endl;
    }
 
    // 销毁线程属性
    pthread_attr_destroy(&attr);
    return 0;
}

pthread_attr_getdetachstate(&attr, &detachstate) 用于获取线程属性对象 attr 中设置的分离状态。它查询的是线程属性对象的配置信息,而不是pthread_detach线程实际运行时的分离状态。

线程分离和线程属性是 pthread 库中非常实用的功能。通过合理使用线程分离,可以避免资源浪费和同步开销;而灵活设置线程属性,则可以根据应用需求优化线程的行为。


http://www.niftyadmin.cn/n/5867000.html

相关文章

从零开始的网站搭建(以照片/文本/视频信息通信网站为例)

本文面向已经有一些编程基础&#xff08;会至少一门编程语言&#xff0c;比如python&#xff09;&#xff0c;但是没有搭建过web应用的人群&#xff0c;会写得尽量细致。重点介绍流程和部署云端的步骤&#xff0c;具体javascript代码怎么写之类的&#xff0c;这里不会涉及。 搭…

【Qt之QQuickWidget】QML嵌入QWidget中

由于我项目开始使用Widgets,换公司后直接使用QML开发&#xff0c;没有了解过如何实现widget到qml过渡&#xff0c;恰逢面试时遇到一家公司希望从widget迁移到qml开发&#xff0c;询问相关实现&#xff0c;一时语塞&#xff0c;很尴尬&#xff0c;粗略研究并总结下。 对qwidget嵌…

Html 5简介(学习笔记)

基本标签 1. 换行标签 <br> <br>2. 链接标签 <a> <a href"https://www.example.com" target"_blank">网站</a>href&#xff1a;指定链接地址。 target&#xff1a; _blank&#xff1a;在新标签页打开。_self&#xff08…

取消票证会把指定的票证从数据库中删除,同时也会把票证和航班 等相关表中的关联关系一起删除。但在删除之前,它会先检查当前用户是否拥有这张票

在做航班智能客服问答系统时会遇到取消票证的场景&#xff0c;这里涉及数据库的操作时会把指定的票证从数据库中删除&#xff0c;同时也会把票证和航班等相关表中的关联关系一起删除。但在删除之前&#xff0c;需要先检查当前用户是否拥有这张票&#xff0c;只有票主才有权限取…

FastAPI系列:Ubuntu部署FastAPI项目实战

这篇文章提供了在Ubuntu上部署FastAPI应用程序的详细指南。首先&#xff0c;读者将学习如何创建项目目录并设置Python虚拟环境&#xff0c;接着安装FastAPI、Uvicorn和Gunicorn等必要依赖。随后&#xff0c;文章指导用户编写基本的FastAPI应用程序代码&#xff0c;并使用Gunico…

文字语音相互转换

目录 1.介绍 2.思路 3.安装python包 3.程序&#xff1a; 4.运行结果 1.介绍 当我们使用一些本地部署的语言模型的时候&#xff0c;往往只能进行文字对话&#xff0c;这一片博客教大家如何实现语音转文字和文字转语音&#xff0c;之后接入ollama的模型就能进行语音对话了。…

【LeetCodehHot100_0x01】

LeetCodeHot100_0x01 1. 两数之和 解题思路&#xff1a; 暴力枚举法、哈希法 【暴力枚举】 class Solution {public int[] twoSum(int[] nums, int target) {int n nums.length;for(int i0;i<n;i) {for(int ji1;j<n;j) {if(nums[i] nums[j] target) {return new in…

第9章:LangChain结构化输出-示例5(基于大模型如何精确匹配POJO的字段)

如何使用LangChain4j框架创建和使用多种AI服务。它通过定义接口和注解,将自然语言处理任务(如情感分析、数字提取、日期提取、POJO提取等)封装为服务,并通过LangChain4j的AiServices动态生成这些服务的实现。 本章主要讲述基于LangChain调用大模型如何进行结构化输出的真实…