Pthread 超时
Posted
技术标签:
【中文标题】Pthread 超时【英文标题】:Pthread timeout 【发布时间】:2012-07-18 12:46:16 【问题描述】:我想做的就是启动一个线程,看看它是否在一定时间内完成。
操作系统:Linux;语言:C++。
我不想使用不可移植的功能(如this answer 中的建议)。
除了使用互斥锁和 条件变量(建议here)?两个线程之间没有共享数据,所以从技术上讲我不需要互斥锁。 我想要的只是,对于启动线程的函数,如果
线程已完成或
过了一段时间。
...并尽可能保持代码简单。
【问题讨论】:
我强烈推荐 boost 线程库,或者如果你有一个支持它们的编译器,C++11 中有一些并发特性。为此,您需要多精确的时间?分析可能是要走的路。 条件变量、布尔标志和互斥体有什么问题? sam:谢谢,我会阅读更多内容。 @Torsten:我想让它尽可能简单,对于这样一个简单的事实来说似乎太过分了。只是觉得我应该问。但是,作为最后的手段,我会谈到这一点。 【参考方案1】:如果你想使用 boost::thread,“通常”的 bool 标志、条件变量、互斥锁方法很简单:
bool ready = false;
boost::mutex mutex;
boost::condition_variable cv;
// function to be executed by your thread
void foo()
// lengthy calculation
boost::mutex::scoped_lock lock( mutex );
ready = true;
cv.notify_one();
// will return, if the thread stopped
bool wait_for_foo( time_point abs_time )
boost::mutex::scoped_lock lock( mutex );
while ( !ready && cv.wait_until( lock, abs_time ) != cv_status::no_timeout )
;
return ready;
好吧,这并不比使用 posix 简单得多;-)
【讨论】:
是的,Nicolai 的解决方案与条件变量的组合,以避免轮询和旋转。不过,我会将它与 posix 一起使用,因为代码稍后将被移植到 linux arm。 (一个互斥体,一个条件变量和一个布尔值,只是为了等待一个线程完成......但这似乎是最好的方法)wait_until
不返回 bool,并且需要 time_point
而不是持续时间。我想你的意思是while (!ready && cv.wait_until(lock, abstime) != cv_status::timeout)
准备一个“简单”的布尔类型不是很危险吗? IMO 您应该在之前添加“volatile”,否则编译器可能会进行值优化,并且在发布代码下您可能会得到不同的行为,对吧?
@zodi volatile 通常与线程无关。如果您有一个编译器/库对,可以让您编写多线程软件,您就可以保证这对像文档中描述的那样工作。
哦,但它在线程方面做了很多 - 来自 msdn 的信息:“volatile 关键字是一个类型限定符,用于声明对象可以在程序中被操作系统、硬件等修改, 或并发执行的线程。(...) Microsoft 特定 - 声明为 volatile 的对象不会在某些优化中使用,因为它们的值可以随时更改。系统总是在它所在的点读取 volatile 对象的当前值请求,即使先前的指令要求来自同一对象的值。"【参考方案2】:
您可以创建计时器线程,一旦计时器到达timeout
,就取消该线程。不需要mutex.code就像:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define TIMEOUT 1*60 //in secend
int count = 0;
pthread_t t_main; //Thread id for main thread
void * timer_thread()
while (TIMEOUT > count)
sleep(1); //sleep for a secand
count++;
printf("killinn main thread\n");
pthread_cancel(t_main); // cancel main thread
void * m_thread()
pthread_t t_timer; //Thread id for timer thread
if (-1 == pthread_create(&t_timer, NULL, timer_thread, NULL))
perror("pthread_create");
return NULL;
//DO your work...
while(1)
sleep(2);
int main()
if ( -1 == pthread_create(&t_main, NULL, m_thread, NULL))
perror("pthread_create");
return -1;
if (-1 == pthread_join(t_main, NULL))
perror("pthread_join");
return -1;
return 0;
【讨论】:
【参考方案3】:你甚至不需要条件变量,你可以让另一个线程在进入时锁定一个互斥锁并在它完成时解锁它,并让启动线程使用pthread_mutex_timedlock
(在旧版本的 POSIX 中是可选的,需要在 POSIX 2008 中)尝试获取互斥锁,如果其他线程尚未完成则超时。
【讨论】:
如何确保启动的线程在等待线程之前获取互斥锁? 唯一的问题是,如果另一个线程在第一个线程检查它之前没有锁定互斥锁,它根本不会等待......所以我尝试在启动线程之前锁定它,但之后它会尝试再次锁定它(timedlock),这是不行的,因为它已经被同一个线程锁定了......我希望我写得足够清楚...... 添加一个初始化为false
的简单布尔值,并让第二个线程在启动时将其翻转为true
(当已经持有互斥锁时)。然后主线程将围绕pthread_mutex_timedlock
循环,释放互斥体并在该布尔值仍然为false
时重试。
这可能非常无效,因为您必须轮询,其次,互斥锁通常在设计时考虑到快速路径。在多处理器机器上,在等待线程被阻塞之前可能会有一些旋转。
是的,不得不承认你对 UP 机器的看法是正确的。继续忘记那些东西的存在:)以上是关于Pthread 超时的主要内容,如果未能解决你的问题,请参考以下文章
C++ 11 替代 pthread_cond_timedwait