【发布时间】: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_lockandpthread_mutex_unlock。 -
忽略大卫指出的
pthread_exit问题,忽略可见性问题:想象一下如果工作线程看到no_of_handles_running == 0,所以它退出循环,然后主线程看到有一个工作线程线程正在运行,因此它不会启动一个,然后工作线程退出而没有看到新的工作。
标签: c multithreading thread-safety pthreads pthread-exit