[英]Can you share mutexes using a common struct between pthreads in C?
I've been working on a multithreading exercise in C using POSIX threads that implements a thread pool design.我一直在使用实现线程池设计的 POSIX 线程在 C 中进行多线程练习。 My strategy was to embed the required and shared concurrency primitives in a struct instance then pass it to every pthread.
我的策略是将所需和共享的并发原语嵌入到结构实例中,然后将其传递给每个 pthread。
I think my approach is flawed.我认为我的方法有缺陷。 It would appear
do_work()
is not dishing out jobs optimally and my book doesn't really explain a method for debugging these types of problems.看起来
do_work()
并没有以最佳方式分配工作,而且我的书并没有真正解释调试这些类型问题的方法。
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include "list.h"
#include "cserver.h"
#define MAX_THREADS 5
struct thread_argvs {
struct list *jobs_to_do;
pthread_mutex_t job_lock;
pthread_cond_t job_signal;
int active;
}
struct job {
int data; // arbitrary for example.
}
void * do_work(void *argv_values);
main(){
// Stores jobs collected from client.
struct job_list;
list_init(&job_list);
struct thread_argvs argvs;
argvs.jobs_to_do = &job_list;
argvs.job_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
argvs.job_signal = (pthread_cond_t) PTHREAD_COND_INITIALIZER;
argvs.active = 1;
pthread_t threads[MAX_THREADS];
for (int i = 0; i < MAX_THREADS; i++){
pthread_create(&thread_list[i], NULL, do_work, (void *) argvs);
}
/* connect to a client in-between here */
for (;;){
struct job *new_job = malloc(sizeof(struct job));
new_job = get_job_from_client();
list_push(&job_list, &new_job);
pthread_cond_signal(&argv.job_signal);
if (new_job.data == -1){ // final job
argv.active = 0;
break;
}
}
for (int i = 0; i < MAX_THREADS; i++) {
pthread_cond_signal(&argv.job_signal);
}
for (int i = 0; i < MAX_THREADS; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
void * do_work(void *argv_values){
struct thread_argvs *argvs = (struct thread_argvs *) argv_values;
struct job *next_job;
while(argvs.active == 1){
next_job = NULL;
pthread_mutex_lock(&(argvs->job_lock));
pthread_cond_wait(&(argvs->job_signal), &(argvs->job_lock));
if (list_size(argvs->jobs_to_do) > 0) {
next_job = list_pop(&jobs_to_do);
}
pthread_mutex_unlock(&(argvs->job_lock));
if (new_job != NULL) {
do_something_with_job(next_job->data);
free(next_job);
next_job = NULL;
}
}
pthread_exit(0);
}
You code can easily deadlock.你的代码很容易死锁。 All the calls to
pthread_cond_signal
can occur while no thread is blocked on the condition variable.当条件变量上没有线程被阻塞时,所有对
pthread_cond_signal
的调用都可能发生。 Then the first thread to call pthread_cond_wait
can just block forever.然后第一个调用
pthread_cond_wait
的线程可以永远阻塞。
You must never call pthread_cond_wait
without first confirming (while holding the mutex!) that the thing you are going to wait for hasn't already happened.在没有首先确认(同时持有互斥锁!)您要等待的事情尚未发生之前,您绝不能调用
pthread_cond_wait
。
From the top:从一开始:
while(argvs.active == 1){
Every bit of storage that is shared between threads must have a synchronization guarantee.线程之间共享的每一位存储都必须有同步保证。 Where is the guarnatee for the line quoted above?
上面引用的行的保证在哪里? Next up;
接下来; Condition variables have no memory.
条件变量没有记忆。 There is no doubt, if somebody sees something like:
毫无疑问,如果有人看到类似的东西:
pthread_mutex_lock(&(argvs->job_lock));
pthread_cond_wait(&(argvs->job_signal), &(argvs->job_lock));
That they missed the message about how condition variables work.他们错过了关于条件变量如何工作的信息。 It is in the name
condition variables
, which means the before waiting upon them, there is some condition
that you must check upon, and failing that condition being true, choose to wait
upon it.它的名称为
condition variables
,这意味着在等待它们之前,有一些condition
必须检查,如果条件不成立,请选择wait
它。
Next: a supplicant of the last - when you awake
on a condition variable, you need to check that the condition is satisfied before continuing.下一步:最后一个请求者 - 当您在条件变量上
awake
时,您需要在继续之前检查条件是否满足。 An example follows:一个例子如下:
Lock(&VeryImportantThing);
while (SomethingVeryImportant is not Set) {
CondWait(&VeryImportantCond, &VeryImportantLock);
}
SomethingVeryImportant = Vanilla;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.