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
在你的线程 运行 的函数中,你开始等待一个条件,但你之前忘记使用互斥量。所以你首先必须在等待条件之前获取互斥锁。
你遇到了我们所说的死锁。
发生的情况是:
- 第一个线程唤醒(pthread_con_wait 函数已经为您获取了锁)
- 然后您再次尝试获取锁 => 死锁,因为您已经拥有锁,所以您自己有点死锁。
正如 Lavigne958 所提到的,在函数 threadThingy() 中存在由 pthread_cond_wait() 引起的死锁,因为它将获取锁。同样,您正试图将其锁定在下一行。这导致了死锁。
有几件事需要检查:
你需要在调用pthread_cond_wait()之前锁定互斥锁。
如果解决了上述问题,使用具有相同互斥量的多个条件变量可能会导致进一步的死锁。
如果您不加入线程,最好使用 PTHREAD_CREATE_DETACHED 属性创建分离线程。
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 了解有关线程的更多信息。
所以我对 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
在你的线程 运行 的函数中,你开始等待一个条件,但你之前忘记使用互斥量。所以你首先必须在等待条件之前获取互斥锁。
你遇到了我们所说的死锁。
发生的情况是:
- 第一个线程唤醒(pthread_con_wait 函数已经为您获取了锁)
- 然后您再次尝试获取锁 => 死锁,因为您已经拥有锁,所以您自己有点死锁。
正如 Lavigne958 所提到的,在函数 threadThingy() 中存在由 pthread_cond_wait() 引起的死锁,因为它将获取锁。同样,您正试图将其锁定在下一行。这导致了死锁。
有几件事需要检查:
你需要在调用pthread_cond_wait()之前锁定互斥锁。
如果解决了上述问题,使用具有相同互斥量的多个条件变量可能会导致进一步的死锁。
如果您不加入线程,最好使用 PTHREAD_CREATE_DETACHED 属性创建分离线程。
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 了解有关线程的更多信息。