0

我有一个工作线程进行轮询活动(它的目标是 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);
}

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

4

1 回答 1

0

感谢上面评论中的所有帮助。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);
}
于 2016-02-18T10:33:37.943 回答