【发布时间】:2021-01-05 17:33:12
【问题描述】:
我正在创建一个多线程文件服务器。我创建了一个线程池来处理来自客户端的请求。这是我的线程池代码:
void *worker_call(void *thread_id){
printf("Initialized thread #%ld \n", (long)thread_id);
//pull in initialized global configs
extern pthread_mutex_t queue_m;
extern pthread_cond_t worker_c;
extern steque_t queue;
while(1){
if (pthread_mutex_lock(&queue_m) != 0){
fprintf(stderr, "An error occured while locking mutex in #%ld \n", (long)thread_id);
}
while(steque_isempty(&queue) == 1){
printf("thread #%ld - Going to sleep...\n", (long) thread_id);
pthread_cond_wait(&worker_c, &queue_m);
printf("thread #%ld - I'm waking up...\n", (long) thread_id);
}
int *work = steque_pop(&queue);
if (pthread_mutex_unlock(&queue_m) != 0){
fprintf(stderr, "An error occured while unlocking mutex in #%ld \n", (long)thread_id);
}
pthread_cond_broadcast(&worker_c);
sleep(1); //added to make sure that the other threads have a chance to wake up
printf("thread #%ld - what is the value of work: %d\n", (long) thread_id, *work);
// process_request(&(work->ctx), work->path, work->arg, (long)thread_id);
free(work);
}
return NULL;
}
为了测试我的线程池是否正确启动并且所有线程都在工作,我创建了以下测试:
int main(){
int nthreads = 6;
pthread_t threads[nthreads];
long thread_ids[nthreads];
pthread_attr_t thread_attr;
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
pthread_attr_setscope(&thread_attr, PTHREAD_SCOPE_SYSTEM);
for(int t=0;t<nthreads;t++){
thread_ids[t] = t;
if( pthread_create(&threads[t],NULL, worker_call, (void *)thread_ids[t]) != 0 ) {
printf("An error occured while creating thread: %d\n", t);
}
}
pthread_attr_destroy(&thread_attr);
//init multi-threading configs
extern pthread_mutex_t queue_m;
pthread_mutexattr_t m_attr;
pthread_mutexattr_init(&m_attr);
pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&queue_m, NULL);
extern pthread_cond_t worker_c;
pthread_cond_init(&worker_c, NULL);
extern steque_t queue;
steque_init(&queue);
//create a simple queue with each item being an int.
//the goal is to simply remove the items from the queue.
for(int i = 0; i < 5; i++){
int *work = malloc(sizeof(int));
*work = i;
steque_enqueue(&queue, work);
}
printf("queue size after creating it: %d\n", steque_size(&queue));
pthread_cond_broadcast(&worker_c);
for(int t=0;t<nthreads;t++){
pthread_join(threads[t], NULL);
}
printf("All the threads finished processing\n");
return 0;
}
现在这段代码成功运行,但是,只有一个线程被唤醒,它完成了所有工作,如下面的输出所示:
Initialized thread #0
thread #0 - Going to sleep...
Initialized thread #1
thread #1 - Going to sleep...
Initialized thread #2
thread #2 - Going to sleep...
Initialized thread #3
thread #3 - Going to sleep...
Initialized thread #4
thread #4 - Going to sleep...
Initialized thread #5
thread #5 - Going to sleep...
queue size after creating it: 5
thread #5 - I'm waking up...
thread #5 - what is the value of work: 0
thread #5 - what is the value of work: 1
thread #5 - what is the value of work: 2
thread #5 - what is the value of work: 3
thread #5 - what is the value of work: 4
thread #5 - Going to sleep...
我的问题是,为什么其他线程没有醒来并从队列中抓取项目?我尝试在发出 pthread_cond_broadcast 后添加一秒钟的延迟,以给其他线程足够的时间来锁定互斥锁,但我没有成功使用该方法。有人看到我做错了吗?
【问题讨论】:
-
在解锁保护它的互斥锁后,您似乎正在访问共享状态。这可能不是主要错误,但至少是其中一个错误。
-
您具体在哪里看到该错误?
-
请分享
worker_call代码。 -
@user58967 worker_call 代码是上面的第一块代码。
-
我认为我错了 - 我误解了
work指向共享数据。
标签: c multithreading posix