您的位置:首页 > 其它

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

2017-02-28 14:20 726 查看

场景

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐