[英]Can you share mutexes using a common struct between pthreads in C?
我一直在使用實現線程池設計的 POSIX 線程在 C 中進行多線程練習。 我的策略是將所需和共享的並發原語嵌入到結構實例中,然后將其傳遞給每個 pthread。
我認為我的方法有缺陷。 看起來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);
}
你的代碼很容易死鎖。 當條件變量上沒有線程被阻塞時,所有對pthread_cond_signal
的調用都可能發生。 然后第一個調用pthread_cond_wait
的線程可以永遠阻塞。
在沒有首先確認(同時持有互斥鎖!)您要等待的事情尚未發生之前,您絕不能調用pthread_cond_wait
。
從一開始:
while(argvs.active == 1){
線程之間共享的每一位存儲都必須有同步保證。 上面引用的行的保證在哪里? 接下來; 條件變量沒有記憶。 毫無疑問,如果有人看到類似的東西:
pthread_mutex_lock(&(argvs->job_lock));
pthread_cond_wait(&(argvs->job_signal), &(argvs->job_lock));
他們錯過了關於條件變量如何工作的信息。 它的名稱為condition variables
,這意味着在等待它們之前,有一些condition
必須檢查,如果條件不成立,請選擇wait
它。
下一步:最后一個請求者 - 當您在條件變量上awake
時,您需要在繼續之前檢查條件是否滿足。 一個例子如下:
Lock(&VeryImportantThing);
while (SomethingVeryImportant is not Set) {
CondWait(&VeryImportantCond, &VeryImportantLock);
}
SomethingVeryImportant = Vanilla;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.