【问题标题】:Posix pthread worker that is only running when needed仅在需要时运行的 Posix pthread worker
【发布时间】:2016-05-29 20:20:38
【问题描述】:

我有一个工作线程正在执行轮询活动(它的目标是 libcurl,但这不相关)。

应用程序的许多操作都可以启动工作线程,但如果它已经在运行,则不应创建新线程。来自应用程序的新请求只需加入任何其他正在进行的轮询。

总之,一个工作线程在无事可做时退出。

代码是:

pthread_t thread = NULL;
struct timespec sleep_val = {0, 20000000};
void *worker_thread(void *threadid)
{
    do {
        poll();
        nanosleep(&sleep_val, NULL);
    } while (no_of_handles_running > 0);
    pthread_exit(NULL);
    thread = NULL;
}

void start_worker_thread_if_needed() {
    if (thread == NULL) {
        pthread_create(&thread, NULL, worker_thread, NULL);
    }
}

我怀疑线程安全。函数 start_worker_thread_if_needed() 可以随时调用任意次数。

那么,如果 start_worker_thread_if_needed() 在我们退出 while 循环并因此中断工作线程时被调用怎么办。如果发生这种情况,条件 if (thread == NULL) 将为 FALSE,因为工作线程被中断并且 pthread_exit + thread = NULL 尚未完成。

所以现在 start_worker_thread_if_needed() 将退出而不创建新线程,但一旦控制权返回到旧工作线程,它将继续到 pthread_exit 行并且工作线程被销毁。

问题将是刚刚触发 start_worker_thread_if_needed() 的请求将丢失,轮询将在下一次调用 start_worker_thread_if_needed() 之前开始。

编辑:这是一个关于互斥锁的建议,但我仍然有同样的疑问。如果主线程在我们退出 while 循环之后和 worker 可以获取互斥锁之前中断会发生什么。然后主线程不创建新线程然后worker退出。

void *worker_thread(void *threadid)
{
    do {
        poll();
        nanosleep(&sleep_val, NULL);
    } while (no_of_handles_running > 0);
    pthread_mutex_lock(&my_mutex);
    thread = NULL;
    pthread_mutex_unlock(&my_mutex);
    pthread_exit(NULL);
}

void start_worker_thread_if_needed() {
    pthread_mutex_lock(&my_mutex);
    if (thread == NULL) {
        pthread_create(&thread, NULL, worker_thread, NULL);
    }
    pthread_mutex_unlock(&my_mutex);
}

我认为我的设置方式存在缺陷,如果有人能提供正确的解决方案,我们将不胜感激。

【问题讨论】:

  • 你期待看到什么?
  • 这就是互斥锁的用途。另外,调用pthread_exit后你不能做任何事情,因为线程已经退出,所以它不会做thread = NULL;操作。
  • 我的期望是上述代码的另一个版本解决了我试图描述的问题。我虽然想使用互斥锁,但我没有看到它如何解决问题。
  • 是的,您的怀疑是有根据的——您所拥有的称为竞争条件。由于thread 变量正被多个线程访问,因此您需要正确保护对它的访问。最常见的方法是使用互斥锁。有关详细信息,请参阅pthread_mutex_lock and pthread_mutex_unlock
  • 忽略大卫指出的pthread_exit问题,忽略可见性问题:想象一下如果工作线程看到no_of_handles_running == 0,所以它退出循环,然后主线程看到有一个工作线程线程正在运行,因此它不会启动一个,然后工作线程退出而没有看到新的工作。

标签: c multithreading thread-safety pthreads pthread-exit


【解决方案1】:

感谢上述 cmets 提供的所有帮助。 Kaylums 建议使用条件变量似乎是一种避免我担心的极端情况的好方法。

最终代码(删除了日志)是下面的代码,它看起来工作得很好。

static int no_of_handles_running;
static int RUN_THREAD = 0;
pthread_t thread = NULL;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv  = PTHREAD_COND_INITIALIZER;;

void *worker_thread(void *threadid)
{
    RUN_THREAD = 1;
    do {
        poll();  //Will update no_of_handles_running
        if (no_of_handles_running == 0) {
            pthread_mutex_lock(&mutex);
            pthread_cond_wait(&cv, &mutex);
            pthread_mutex_unlock(&mutex);
        }
    } while (RUN_THREAD);
    thread = NULL;
    pthread_exit(NULL);

}
void start_worker_thread() {
    if (thread == NULL) {
        int rc = pthread_create(&thread, NULL, worker_thread, NULL);
        if (rc){
            return;
        } 
    }
    pthread_mutex_lock(&mutex);
    pthread_cond_signal(&cv);
    pthread_mutex_unlock(&mutex);
}

void stop_worker_thread() {
    RUN_THREAD = 0;
    pthread_mutex_lock(&mutex);
    pthread_cond_signal(&cv);
    pthread_mutex_unlock(&mutex);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-01
    • 2018-09-07
    • 2011-03-29
    • 1970-01-01
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多