C Pthread: 运行 only 10 threads simultaneously (这里有什么问题)

C Pthread: Running only 10 threads simultaneously (what is the problem here)

所以我对 C 中 pthread 的整个概念还很陌生,但请听我说完。我有以下代码:

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


static pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;

static pthread_cond_t   endCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t   startCond = PTHREAD_COND_INITIALIZER;

void * threadThingy(void * n){
    pthread_cond_wait(&startCond, &mutex);
    printf("%d: RAND: %d\n", *((int*)n), rand());

    //Lock mutex before broadcasting to main thread
    pthread_mutex_lock(&mutex);
    pthread_cond_broadcast(&endCond);
    pthread_mutex_unlock(&mutex);


    free(n);
    fflush(stdout);
    return 0;
}


int main(void){
    printf("Starting\n");
    pthread_t threads[100];
    int i = 0;

    while(i < 10){
        int *arg = malloc(sizeof(int));
        *arg = i;
        pthread_create(&threads[i], NULL, threadThingy, arg);
        i++;
    }

    pthread_mutex_lock(&mutex);
    pthread_cond_broadcast(&startCond);

    int finished = 0;

    while(finished <= 100){
        pthread_cond_wait(&endCond, &mutex);

        //Lock mutex so no other requests can come in
        pthread_mutex_lock(&mutex);
        finished++;

        int *arg = malloc(sizeof(int));
        *arg = 11;
        pthread_create(threads[i], NULL, threadThingy, arg);
        i++;
        pthread_cond_broadcast(&startCond);
        pthread_mutex_unlock(&mutex);

    }

    printf("Stopping\n");

    sleep(1000);
}

整个目标是 运行(仅)100 个线程中同时有 10 个线程。我的想法是启动 10 个线程,而不是等到一个线程完成后再启动另一个线程。所以我让程序等到一个线程 returns,然后我启动一个新线程,以便替换刚刚返回的线程。我错过了什么?因为现在我只得到这个作为输出:

Starting 0: RAND: 1804289383

在你的线程 运行 的函数中,你开始等待一个条件,但你之前忘记使用互斥量。所以你首先必须在等待条件之前获取互斥锁。

你遇到了我们所说的死锁。

发生的情况是:

  1. 第一个线程唤醒(pthread_con_wait 函数已经为您获取了锁)
  2. 然后您再次尝试获取锁 => 死锁,因为您已经拥有锁,所以您自己有点死锁。

正如 Lavigne958 所提到的,在函数 threadThingy() 中存在由 pthread_cond_wait() 引起的死锁,因为它将获取锁。同样,您正试图将其锁定在下一行。这导致了死锁。

有几件事需要检查:

  1. 你需要在调用pthread_cond_wait()之前锁定互斥锁。

  2. 如果解决了上述问题,使用具有相同互斥量的多个条件变量可能会导致进一步的死锁。

  3. 如果您不加入线程,最好使用 PTHREAD_CREATE_DETACHED 属性创建分离线程。

  4. N个线程的问题运行同时可以用一个信号量或一个条件变量(和一个互斥量)来解决。下面给出了带有信号量的示例。

    #include <stdio.h>
    #include <pthread.h>
    #include <semaphore.h>
    #include <unistd.h>
    
    sem_t mysem;
    #define NUM_CONCURRENT_THREADS 4
    #define MAX_THREADS 40
    
    void *thread(void *arg)
    {
            printf("Thread id %ld: started\n", pthread_self());
            sleep(5); // Do some work
            printf("Thread id %ld: Exiting\n", pthread_self());
            sem_post(&mysem);
            return NULL;
    }
    
    
    int main()
    {
            pthread_t t[MAX_THREADS];
            pthread_attr_t attr;
            int rc, i = 0;
    
            sem_init(&mysem, 0, NUM_CONCURRENT_THREADS);
            rc = pthread_attr_init(&attr);
            rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    
            printf("\nParent begin\n");
            while(i < MAX_THREADS)
            {
                    sem_wait(&mysem);
                    pthread_create(&t[i], &attr, thread, NULL);
                    i++;
            }
            printf("\nParent end.\n");
    
            sem_destroy(&mysem);
            return 0;
    }
    

请查看博客 Tech Easy 了解有关线程的更多信息。