【发布时间】:2013-02-25 23:33:08
【问题描述】:
我遇到的问题是:我的“父级”经历了一个从 0 到 4 的 for 循环。在每次迭代中,我有 3 个线程要打印出它们的 12 个数字的“段” (0 到 11)。
例如,当父循环为0时,线程0会打印出0,线程1会打印出4,线程2会打印出8。
当父循环为1时,线程0会打印出1,线程1会打印出5,线程2会打印出9。
理想情况下,输出为 0 1 2 3 4 5 6 7 8 9 10 11 。我知道您无法确定线程何时运行,因此不会完全按照该顺序运行,但我至少希望在线程打印 3 4 或 5 之前打印 0 1 和 2。
这就是我遇到的问题。似乎一个线程或另一个线程被留在尘土中并且没有打印出它的片段,或者没有完全打印出它的片段以及其他线程。这是我试图完全理解信号量的问题。
我有两个信号量,一个在线程工作时阻塞父级(生产者?),另一个阻塞每个线程,直到生产者增加到下一个索引。我认为通过这种方式我可以强迫他们在继续之前等待对方完成,但由于某种原因我遇到了问题。
这是我的代码:
#include <semaphore.h>
#include <stdio.h>
#include <pthread.h>
#define maxNum 12
sem_t parentSem;
sem_t threadSem;
int finishedThreads;
int done = 0;
int stuff[12];
int i;
void* threadFunction(int m){
int printNum;
int baseNum;
//Determine the value the thread should start at
baseNum = (double)(maxNum/3) * m;
while(!done){ //ensure thread doesn't exit before parent is done with whole loop
//wait for parent to increment
sem_wait(&threadSem);
printNum = baseNum + i;
//keep track of how many threads are finished to let parent continue
finishedThreads++;
if(finishedThreads == 3){
//let parent continue if all threads are finished
sem_post(&parentSem);
}
}
}
int main(int argc, char** argv[]){
sem_init(&parentSem, 0, 1);
sem_init(&threadSem, 0, 0);
int rc;
pthread_t threads[3];
int l;
for(l = 0; l < 12; l++){
stuff[l] = l;
}
int j;
for(j = 0; j < 3; j++){
rc = pthread_create(&threads[i], NULL, threadFunction, (void*) j);
}
int k;
for(i = 0; i < 4; i++){
sem_wait(&parentSem); //wait for children here (initially sem set to 1)
finishedThreads = 0; //set finished thread counter to 0
for(k = 0; k < 3; k++){
//increment thread semaphore to 3 so each thread can run
sem_post(&threadSem);
}
}
for(i = 1; i < 3; i++){
pthread_join(threads[i], NULL);
}
}
如何确保所有线程在父级递增之前运行?我如何确保所有线程每“一轮”运行而没有任何卡在后面?有时同一个线程运行两次而不是每个线程运行一次.....帮助?
非常感谢大家的帮助。
编辑:新代码状态:(线程函数)
while(!done){
printf("Thread %d not done yet...\n", m);
if(m == 0){
sem_wait(&threadSem0);
}else if(m == 1){
sem_wait(&threadSem1);
}else if(m == 2){
sem_wait(&threadSem2);
}
printNum = baseNum + i;
printf("Thread %d past waiting, number segment: %d\n", m, printNum);
finishedThreads++;
if(finishedThreads == 3){
sem_post(&parentSem);
}
}
父部分:
for(i = 0; i < 4; i++){
printf("In parent for loop, counter: %d\n", i);
printf("Parent past wait semaphore\n");
finishedThreads = 0;
if(i == 3) done = 1;
sem_post(&threadSem0);
sem_post(&threadSem1);
sem_post(&threadSem2);
sem_wait(&parentSem);
}
for(i = 1; i < 3; i++){
pthread_join(threads[i], NULL);
}
【问题讨论】:
-
您可能应该使用条件变量,并且您必须有一个关于访问
finishedThreads的关键部分。没有临界区,代码就有缺陷(有时会丢失计数)。 -
我查看了条件变量。我不知道如何正确使用它们。你是说我应该在我增加finishedThreads的地方放一个互斥锁?
标签: c multithreading pthreads semaphore