linux - 使用 C 中的 pthread 保持线程数恒定

标签 linux multithreading synchronization pthreads mutex

我试图找到一个解决方案,以便使用 pthreads 在 C 中保持 linux 下工作线程的数量恒定,但我似乎无法完全理解以下代码有什么问题:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define MAX_JOBS 50
#define MAX_THREADS 5

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int jobs = MAX_JOBS;
int worker = 0;
int counter = 0;

void *functionC() {
  pthread_mutex_lock(&mutex1);
  worker++;
  counter++;
  printf("Counter value: %d\n",counter);
  pthread_mutex_unlock(&mutex1);

  // Do something...
  sleep(4);

  pthread_mutex_lock(&mutex1);
  jobs--;
  worker--;
  printf(" >>> Job done: %d\n",jobs);
  pthread_mutex_unlock(&mutex1);
}

int main(int argc, char *argv[]) {
  int i=0, j=0;
  pthread_t thread[MAX_JOBS];

  // Create threads if the number of working threads doesn't exceed MAX_THREADS
  while (1) {
    if (worker > MAX_THREADS) {
      printf(" +++ In queue: %d\n", worker);
      sleep(1);
    } else {
      //printf(" +++ Creating new thread: %d\n", worker);
      pthread_create(&thread[i], NULL, &functionC, NULL);
      //printf("%d",worker);
      i++;
    }
    if (i == MAX_JOBS) break;
  }

  // Wait all threads to finish
  for (j=0;j<MAX_JOBS;j++) {
    pthread_join(thread[j], NULL);
  }

  return(0);
}

如果工作线程的数量低于某个阈值,则 while (1) 循环会不断创建线程。每次工作线程的全局计数器递增(线程创建)和递减(作业完成)时,互斥体应该锁定关键部分。我认为它可以正常工作并且在大多数情况下都可以,但是奇怪的事情发生了......

例如,如果我评论(如本片段中所示) printf//printf("+++ 创建新线程:%d\n", worker); while (1) 似乎一次生成一个随机数(根据我的经验为 18-25)线程(functionC 打印出“计数器值:从 1 到 18-25”...),而不是尊重 IF 条件环形。如果我包含 printf,则循环似乎“几乎”以正确的方式运行...这似乎暗示缺少“互斥”条件,我应该将其添加到 main() 中的循环中,以便在 MAX_THREADS 时有效锁定线程已达到,但在过去几天更改此代码很多次之后,我现在有点迷失了。我错过了什么?

请让我知道我应该更改什么以保持线程数恒定,似乎我离解决方案并不太远......希望...... :-)

提前致谢!

最佳答案

您的问题是,直到新线程实际启动并开始运行之前,worker 才会递增 - 与此同时,主线程循环,检查 workers,发现它没有改变,并启动另一个线程。它可以重复多次,创建太多线程。

因此,当您决定创建新线程时,需要在主线程中增加 worker

您还有另一个问题 - 您应该使用条件变量让主线程休眠,直到它启动另一个线程,而不是使用带有 sleep(1); 的忙等待循环。完整的固定代码如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

#define MAX_JOBS 50
#define MAX_THREADS 5

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
int jobs = MAX_JOBS;
int workers = 0;
int counter = 0;

void *functionC() {
  pthread_mutex_lock(&mutex1);
  counter++;
  printf("Counter value: %d\n",counter);
  pthread_mutex_unlock(&mutex1);

  // Do something...
  sleep(4);

  pthread_mutex_lock(&mutex1);
  jobs--;
  printf(" >>> Job done: %d\n",jobs);

  /* Worker is about to exit, so decrement count and wakeup main thread */
  workers--;
  pthread_cond_signal(&cond1);

  pthread_mutex_unlock(&mutex1);
  return NULL;
}

int main(int argc, char *argv[]) {
  int i=0, j=0;
  pthread_t thread[MAX_JOBS];

  // Create threads if the number of working threads doesn't exceed MAX_THREADS
  while (i < MAX_JOBS) {
    /* Block on condition variable until there are insufficient workers running */
    pthread_mutex_lock(&mutex1);
    while (workers >= MAX_THREADS)
        pthread_cond_wait(&cond1, &mutex1);

    /* Another worker will be running shortly */
    workers++;
    pthread_mutex_unlock(&mutex1);

    pthread_create(&thread[i], NULL, &functionC, NULL);
    i++;
  }

  // Wait all threads to finish
  for (j=0;j<MAX_JOBS;j++) {
    pthread_join(thread[j], NULL);
  }

  return(0);
}

请注意,尽管这有效,但它并不理想 - 最好预先创建您想要的线程数量,并让它们循环,等待工作。这是因为创建和销毁线程会产生很大的开销,而且它通常会简化资源管理。重写后的代码版本如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

#define MAX_JOBS 50
#define MAX_THREADS 5

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int jobs = MAX_JOBS;
int counter = 0;

void *functionC()
{
  int running_job;

  pthread_mutex_lock(&mutex1);
  counter++;
  printf("Counter value: %d\n",counter);

  while (jobs > 0) {
    running_job = jobs--;
    pthread_mutex_unlock(&mutex1);

    printf(" >>> Job starting: %d\n", running_job);

    // Do something...
    sleep(4);

    printf(" >>> Job done: %d\n", running_job);

    pthread_mutex_lock(&mutex1);
  }
  pthread_mutex_unlock(&mutex1);

  return NULL;
}

int main(int argc, char *argv[]) {
  int i;
  pthread_t thread[MAX_THREADS];

  for (i = 0; i < MAX_THREADS; i++)
    pthread_create(&thread[i], NULL, &functionC, NULL);

  // Wait all threads to finish
  for (i = 0; i < MAX_THREADS; i++)
    pthread_join(thread[i], NULL);

  return 0;
}

关于linux - 使用 C 中的 pthread 保持线程数恒定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5150630/

相关文章:

java - JVM 语言是受 Java 内存模型约束还是仅受 Java 编程语言约束?

sql - 在 Oracle 中保持表同步

Java:通过反射多次访问同步方法?

c - 为什么 gcc 提示已经存在的库找不到?

linux - 如何在 Makefile 中隐藏编译信息?

c++ - 在线程错误 C2064 : term does not evaluate to a function taking 0 arguments

java - 当 System.out.println 出现在临界区时,多个线程显示异常值

c - Kylix 中的 TEvent.WaitFor

linux - 通过 SSH 连接 OpenGL 时出现问题

linux - 为什么只包含一行的文件中有一个 LF 字符? (在Linux中)