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 超时的主要内容,如果未能解决你的问题,请参考以下文章

pthread_cond_timedwait时间设置

C++ 11 替代 pthread_cond_timedwait

pthread_kill()vs pthread_cancel()终止阻塞I / O的线程

pthread_mutex_init返回值22代表啥含义

如何在android下采用相对时间,实现超时等待的功能

pthread_once的pthread_once