jthread库分析二:JThread类

JThread类的定义如下:

class JThread
{
public:
	JThread();
	virtual ~JThread();
	int Start();
	int Kill();
	virtual void *Thread() = 0;
	bool IsRunning();
	void *GetReturnValue();
protected:
	void ThreadStarted();
};
可以通过继承JThread类创建自己的线程。Thread方法将会在新线程中执行,子类应该实现Thread方法。实现的Thread方法中必须立即调用ThreadStarted方法。

为了启动线程,需要调用Start方法。只有当你的Thread函数调用了ThreadStarted方法后,Start方法才会返回。当Start方法返回后,你的Thread实现一定在运行。当然,你可以调用IsRunning函数检查线程是否还在运行。如果线程已结束,那么你可以调用GetReturnValue获得返回值。

最后,如果你的线程有问题,你可以调用Kill函数终止线程执行。如果线程中使用了mutex,那么kill之后,mutex可能处于locked状态,这可能导致其它线程阻塞。


Linux下实现 

JThread私有成员

class JThread
{
public:
	JThread();
	virtual ~JThread();
// ...
protected:
	void ThreadStarted();
private:
//...
	static void *TheThread(void *param);	
	pthread_t threadid;

	void *retval;
	bool running;
	
	JMutex runningmutex;
	JMutex continuemutex,continuemutex2;
	bool mutexinit;
};

具体实现如下:

JThread::JThread()
{
	retval = NULL;
	mutexinit = false;
	running = false;
}

JThread::~JThread()
{
	Kill();
}

int JThread::Start()
{
	int status;

	//init runningmutex, continuemutex, continuemutex2
	if (!mutexinit)
	{
		if (!runningmutex.IsInitialized())
		{
			if (runningmutex.Init() < 0)
				return ERR_JTHREAD_CANTINITMUTEX;
		}
		if (!continuemutex.IsInitialized())
		{
			if (continuemutex.Init() < 0)
				return ERR_JTHREAD_CANTINITMUTEX;
		}
		if (!continuemutex2.IsInitialized())
		{
			if (continuemutex2.Init() < 0)
				return ERR_JTHREAD_CANTINITMUTEX;
		}
		mutexinit = true;
	}
	
	runningmutex.Lock();
	if (running)
	{
		runningmutex.Unlock();
		return ERR_JTHREAD_ALREADYRUNNING;
	}
	runningmutex.Unlock();
	
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);//detached状态的线程,在结束的时候,会自动释放该线程所占用的资源。
	
	continuemutex.Lock();
	status = pthread_create(&threadid,&attr,TheThread,this);  //创建线程,在这里 将会有两个线程分支, main thread和执行用户代码的子线程t	
	pthread_attr_destroy(&attr);
	if (status != 0)
	{ // 线程创建失败
		continuemutex.Unlock();
		return ERR_JTHREAD_CANTSTARTTHREAD;
	}
	
	/* Wait until 'running' is set */
	
	runningmutex.Lock();			
	while (!running)
	{
		runningmutex.Unlock();
		
		struct timespec req,rem;

		req.tv_sec = 0;
		req.tv_nsec = 1000000;
		nanosleep(&req,&rem);

		runningmutex.Lock();
	}
	runningmutex.Unlock();
/*Line-M1*/	
	continuemutex.Unlock();
/*Line-M2*/	
	continuemutex2.Lock(); // 主线程在此阻塞, 直到子线程调用了 ThreadStarted 方法
	continuemutex2.Unlock();
/*Line-M3*/
        return 0;
}

int JThread::Kill()
{
	runningmutex.Lock();			
	if (!running)
	{
		runningmutex.Unlock();
		return ERR_JTHREAD_NOTRUNNING;
	}
	pthread_cancel(threadid);
	running = false;
	runningmutex.Unlock();
	return 0;
}

bool JThread::IsRunning()
{
	bool r;
	
	runningmutex.Lock();			
	r = running;
	runningmutex.Unlock();
	return r;
}

void *JThread::GetReturnValue()
{
	void *val;
	
	runningmutex.Lock();
	if (running)
		val = NULL;
	else
		val = retval;
	runningmutex.Unlock();
	return val;
}

void *JThread::TheThread(void *param)
{
	JThread *jthread;
	void *ret;
	
	jthread = (JThread *)param;
	
	jthread->continuemutex2.Lock();//continuemutex2加锁, 在Thread方法中调用ThreadStarted后解锁
	jthread->runningmutex.Lock();
	jthread->running = true; //线程开始运行,设置线程状态true
	jthread->runningmutex.Unlock();
/*Line-T1*/	
	jthread->continuemutex.Lock();
	jthread->continuemutex.Unlock();
/*Line-T2*/
	ret = jthread->Thread(); //调用 用户实现的方法

	jthread->runningmutex.Lock();
	jthread->running = false; //线程结束运行,设置线程状态false
	jthread->retval = ret;
	jthread->runningmutex.Unlock();

	return NULL;
}

void JThread::ThreadStarted() // 参考TheThread方法
{
	continuemutex2.Unlock();
/*Line-T3*/
}


假设主线程为m, 子线程为t。线程m在调用Start方法时,创建了子线程t。线程t执行TheThread方法, 而TheThread方法中调用了用户实现的方法Thread

线程m和t共有3次同步的过程:

  • 第1次通过runningmutex同步线程的状态running变量, 此时线程m执行到Line-M1,线程t执行到Line-T1;
  • 第2次通过continuemutex再次同步线程, 此时线程m执行到Line-M2,线程t执行到Line-T2;
  • 第3次通过continuemutex2同步线程, 此时线程m执行到Line-M3并返回,线程t执行到ThreadStarted方法中的Line-T3。显然,若用户不在Thread方法中调用ThreadStarted方法, 主线程m将阻塞,即使子线程结束也不会返回。


Windows下实现

windows下的实现与Linux下实现类似,不同的是创建线程,终止线程的方法不一样。在Windows下采用_beginthreadex创建线程,TerminateThread终止线程。执行流程这里不再重复。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值