【发布时间】:2017-10-23 12:05:44
【问题描述】:
假设我的代码在访问某些共享状态时持有互斥锁。在某些时候,我确定我需要创建一个新线程,因此调用 pthread_create,同时仍然持有互斥锁。这被认为是安全的吗?
假设我的共享状态是一个全局计数器,它跟踪成功创建的 pthread 的数量,另一个线程使用这个计数器在屏幕上实时显示信息。此外,我不希望 pthread 的数量大于某个最大值(例如 10 表示确定性)。
假设计数器当前为 9。如果我在调用 pthread_create 之前递增计数器然后释放互斥锁,则 pthread_create 可能会失败,然后计数器错误地显示比我实际更多的线程 (10)创建成功 (9)。
另一方面,如果我首先释放互斥锁,然后调用 pthread_create,然后如果调用成功,则重新获取互斥锁以递增计数器,然后在释放互斥锁和从 pthread_create 返回之间,另一个线程可能有也称为 pthread_create 并将计数器递增(至 10)。因此,我将创建第 11 个 pthread,计数器变为 11。但我应该创建的 pthread 不超过 10 个。
因此,保证共享状态一致性的唯一方法似乎是在调用 pthread_create 时保持互斥锁。但我知道,一般来说,一个人不应该在持有互斥锁的同时调用未知代码,所以我不知道在这种情况下可以做什么。
编辑:以下是一些可能会出现此问题的示例代码
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *do_stuff(void *arg);
int pthreads_counter = 0;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
#define MAX_PTHREADS_COUNT 10
/* Could potentially be called from multiple threads simultaneously */
int create_thread_and_increment_counter()
{
pthread_t thread;
if (pthread_mutex_lock(&mtx) != 0)
return -1;
if (pthreads_counter >= MAX_PTHREADS_COUNT) {
pthread_mutex_unlock(&mtx);
return -1;
}
++pthreads_counter;
if (pthread_create(&thread, NULL, do_stuff, NULL) != 0) {
--pthreads_counter;
pthread_mutex_unlock(&mtx);
return -1;
}
pthread_mutex_unlock(&mtx);
return 0;
}
void *do_stuff(void *arg)
{
/* do stuff */
return NULL;
}
/* Created somewhere else */
void *display_thread(void *arg)
{
while (1) {
if (pthread_mutex_lock(&mtx) != 0)
break;
printf("%d\n", pthreads_counter);
pthread_mutex_unlock(&mtx);
usleep(1000000);
}
return NULL;
}
【问题讨论】:
标签: multithreading pthreads mutex shared-state