[并发并行]_[任务停止]_[使用Pthread的线程本地存储来停止任务执行]

本文介绍了一种在多线程应用中,特别是线程池环境下,如何优雅地停止线程的方法,避免直接使用pthread_cancel等可能导致线程资源浪费的API。通过设置线程本地存储中的状态变量,实现业务逻辑的中断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景

1.多线程应用里, 线程基本上都是出自线程池, 那么基本不能使用pthread_cancel这类API, 因为它会终止线程运行, 线程终止后不能再次循环使用, 这对性能要求高的软件时基本是不会用pthread_cancel来停止逻辑运行的.

2.自行设计的可预测伪线程停止,其实就是停止执行当前的业务逻辑,并不是终止线程, 让线程回归线程池. 目前我发现的方案基本上离不开对状态变量的判断. (比较忙, 没有参考那些其他大公司的开源项目, 如有不足,请批评指正), 这里只说我发现的一种方案, 使用specific data,线程本地存储.

说明

1.pthread也可以类似Win32一样使用线程本地存储, 使用方式是差不多的, 参考线程本地存储. 关键的地方就是创建一个默认key来存储任务对象, 通过判断任务对象的值来中断逻辑执行. 大部分情况下是线程A 正在执行逻辑A, 线程B接收到客户终止任务执行请求, 通过获取到这个任务对象A, 并修改任务对象A的状态, 这时线程A 判断到任务对象A的状态时Abort时, 退出执行循环.

例子


// test-pthread-stop.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <stdint.h>

#include "pthread.h"

pthread_key_t gTaskKey;

typedef enum kTaskStatus1
{
    kTaskStatusOk = 0,
    kTaskStatusDoing,
    kTaskStatusAbort,
    kTaskStatusFinish
}kTaskStatus;

struct IPCPacket
{
    uint64_t _id;               //Packet id
    uint8_t status;         //Packet 状态
    uint32_t command_type;      //Packet 命令类型

    void* data;                 //接收和发送数据.
    uint32_t data_length;       //数据长度.
};

static bool TestIsAbort(){
    void* data = pthread_getspecific(gTaskKey);

    // pthread specific data 默认是 NULL.
    IPCPacket* packet = (IPCPacket*)data;
    if(packet && packet->status == kTaskStatusAbort)
        return true;
    return false;
}

static void DoWork(void* data){
    for(int i = 0; ; ++i){
        Sleep(1000);
        if(TestIsAbort()){
            std::cout << "StartThread Abort: " << i << std::endl;
            break;
        }else{
            std::cout << "StartThread: " << i << std::endl;
        }
    }
}

void* StartThread(void* data){

    IPCPacket* task = (IPCPacket*)data;
    pthread_setspecific(gTaskKey,task);
    DoWork(data);

    return NULL;
}

void TestThreadAbort(){

    pthread_key_create(&gTaskKey,NULL);

    IPCPacket task;
    memset(&task,0,sizeof(task));

    int count = 0;
    pthread_t t1;
    pthread_create(&t1,NULL,StartThread,&task);

    Sleep(3000);
    task.status = kTaskStatusAbort;
    pthread_join(t1,NULL);
}

int _tmain(int argc, _TCHAR* argv[])
{

    std::cout << "TestThreadAbort Begin" << std::endl;
    TestThreadAbort();
    std::cout << "TestThreadAbort End" << std::endl;
    system("pause");
    return 0;
}


输出:

TestThreadAbort Begin
StartThread: 0
StartThread: 1
StartThread Abort: 2
TestThreadAbort End

参考

Programming With POSIX Threads

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

白行微

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

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

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

打赏作者

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

抵扣说明:

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

余额充值