C中的Pthread_cond_wait

问题描述 投票:0回答:1

Problem

编辑:正如评论中指出的那样,我对pthread_cond_wait犯了一个错误,导致它永远不会退出线程。

我正在C中进行多线程分配,我需要使用多个线程来使用shearsort对4x4数组进行排序,但我无法做到这一点,因为 每当我使用pthread_join时,应用程序永远不会结束,它永远不会加入。应用程序保持原样,直到我控制C结束它。 我弄乱了我的pthread_cond_wait意味着一些线程永远不会继续。

我想我问我应该如何使用pthread_wait_cond,因为当我有if / else语句的两侧都有pthread_wait_cond时它不会输出任何东西而只是卡住了。

此外,这现在是主要问题的一部分,但我看到很多人在for循环中启动pthreads,但是当我尝试传入函数的I变量似乎是随机设置时,有时每个线程获得正确它自己的编号,但有时会创建具有相同编号的线程。我是否需要使用某种互斥量来确保pthread_create以原子方式发生,我该怎么做?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sched.h>
#include <fcntl.h>
#include <pthread.h>

#define N 4

void intSwap(int *a, int *b);
void *shearSort(void *rowCol);


pthread_cond_t sort0  =  PTHREAD_COND_INITIALIZER;
pthread_cond_t sort1  =  PTHREAD_COND_INITIALIZER;
pthread_cond_t sort2  =  PTHREAD_COND_INITIALIZER;
pthread_cond_t sort3  =  PTHREAD_COND_INITIALIZER;

pthread_cond_t writeArray  =  PTHREAD_COND_INITIALIZER;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

int array[N][N];

pthread_t thread[N];

void *shearSort(void *rowCol) {
  int x = 0, y = 0;
  printf("rowCol = %d", ((int)*(int*)rowCol));
  pthread_mutex_lock(&lock);

  if (((int)*(int*)rowCol)%2 == 0) {
    for(x = 0; x < N-1; x++) {
      for (y = 0; y < N-x-1; y++) {

        //pthread_cond_wait(&writeArray, &lock);
        if (array[((int)*(int*)rowCol)][y] > array[((int)*(int*)rowCol)][y+1]) {
          printf("rowCol = %d, i = %d, j = %d Swapping %d & %d\n", ((int)*(int*)rowCol), x, y, array[((int)*(int*)rowCol)][y], array[((int)*(int*)rowCol)][y+1]);
          intSwap(&array[((int)*(int*)rowCol)][y], &array[((int)*(int*)rowCol)][y+1]);
        }
        //pthread_cond_signal(&writeArray);

      }
    }
  }
  else {
    for(x = 0; x < N-1; x++) {
      for (y = 0; y < N-x-1; y++) {

        //pthread_cond_wait(&writeArray, &lock);
        if (array[((int)*(int*)rowCol)][y] < array[((int)*(int*)rowCol)][y+1]) {
          printf("rowCol = %d, i = %d, j = %d Swapping %d & %d\n", ((int)*(int*)rowCol), x, y, array[((int)*(int*)rowCol)][y], array[((int)*(int*)rowCol)][y+1]);
          intSwap(&array[((int)*(int*)rowCol)][y], &array[((int)*(int*)rowCol)][y+1]);
        }
        //pthread_cond_signal(&writeArray);

      }
    }
  }
  pthread_mutex_unlock(&lock);
  if(((int)*(int*)rowCol) == 1) {
    //pthread_join(thread[0], NULL);
  }
  if(((int)*(int*)rowCol) == 2) {
    //pthread_join(thread[0], NULL);
    //pthread_join(thread[1], NULL);
  }
  if(((int)*(int*)rowCol) == 3) {
    //pthread_join(thread[0], NULL);
    //pthread_join(thread[1], NULL);
    //pthread_join(thread[2], NULL);
  }

  pthread_exit(NULL);
}

void intSwap(int *a, int *b) {
  int temp = *a;
  *a = *b;
  *b = temp;
}

int main () {

  FILE *input;

  int i = 0, j = 0;

  input = fopen("input.txt" , "r");

  if (input != NULL) {
    for (i = 0; i < N; i++) {

      for (j = 0; j < N; j++) {
        fscanf(input, "%d, ", &array[i][j]);
        printf("%d, ", array[i][j]);
      }
      printf("\n");
    }
    printf("\n");
  }
  else {
    perror( "There's a problem with the input.txt file, it doesn't seem to be there.");
exit( EXIT_FAILURE );
  }

  // for (i = 0; i < N; i++) {
    // pthread_create(&thread[i], NULL, shearSort, (void *)&i);
  // }

  // for (i = 0; i < N; i++) {
    // pthread_join(thread[i], NULL);
  // }

  int num0 = 0, num1 = 1, num2 = 2, num3 = 3;
  pthread_create(&thread[0], NULL, shearSort, (void *)&num0);
  pthread_create(&thread[1], NULL, shearSort, (void *)&num1);
  pthread_create(&thread[2], NULL, shearSort, (void *)&num2);
  pthread_create(&thread[3], NULL, shearSort, (void *)&num3);

  pthread_join(thread[num0], NULL);
  pthread_join(thread[1], NULL);
  pthread_join(thread[2], NULL);
  pthread_join(thread[3], NULL);


  for (i = 0; i < N; i++) {
    for (j = 0; j < N; j++) {
      printf("%d, ", array[i][j]);
    }
    printf("\n");
  }
return 0
}

当我运行上面的代码时,没有对else的pthread_cond_wait的评论我从命令行得到了这个输出然后它就停止了。

*CommandLineOutput*

5, 3, 9, 10,
2, -3, 11, 8,
20, 17, 19, 30,
24, 21, -2, 16,

rowCol = 0rowCol = 0, i = 0, j = 0 Swapping 5 & 3
rowCol = 1rowCol = 2rowCol = 2, i = 0, j = 0 Swapping 20 & 17
rowCol = 2, i = 0, j = 1 Swapping 20 & 19
^C

现在当我按原样运行代码时,我得到了这个输出:

Output

5, 3, 9, 10,
2, -3, 11, 8,
20, 17, 19, 30,
24, 21, -2, 16,

rowCol = 0rowCol = 0, i = 0, j = 0 Swapping 5 & 3
rowCol = 1rowCol = 1, i = 0, j = 1 Swapping -3 & 11
rowCol = 1, i = 0, j = 2 Swapping -3 & 8
rowCol = 1, i = 1, j = 0 Swapping 2 & 11
rowCol = 1, i = 1, j = 1 Swapping 2 & 8
rowCol = 2rowCol = 2, i = 0, j = 0 Swapping 20 & 17
rowCol = 2, i = 0, j = 1 Swapping 20 & 19
rowCol = 3rowCol = 3, i = 0, j = 2 Swapping -2 & 16
3, 5, 9, 10,
11, 8, 2, -3,
17, 19, 20, 30,
24, 21, 16, -2,
c multithreading thread-safety pthreads
1个回答
1
投票

在调用pthread_cond_wait之前,确保其他线程唤醒它,所以在调用pthread_cond_wait之前,需要判断是否有其他线程使用array,如果使用array则需要等待,否则直接操作它

看下面实现的函数acquireWriteArrayreleaseWriteArray

在pthread_create中,您可以直接传递值,而不是传递地址:

pthread_create(&thread[i], NULL, shearSort, (void *)(long)i);

修改后的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sched.h>
#include <fcntl.h>
#include <pthread.h>

#define N 4

void intSwap(int *a, int *b);
void *shearSort(void *rowCol);

pthread_cond_t writeArray  =  PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int array[N][N];
pthread_t thread[N];
volatile int writeBusy = 0;

void acquireWriteArray()
{
    pthread_mutex_lock(&lock);
    while (writeBusy) {
        pthread_cond_wait(&writeArray, &lock);
    }
    writeBusy = 1;
}

void releaseWriteArray()
{
    writeBusy = 0;
    pthread_cond_signal(&writeArray);
    pthread_mutex_unlock(&lock);
}

void *shearSort(void *rowCol)
{
    int x = 0, y = 0;
    int idx = (long)rowCol;
    printf("rowCol = %d.\n", idx);

    if (idx % 2 == 0) {
        for(x = 0; x < N - 1; x++) {
            for (y = 0; y < N - x - 1; y++) {

                acquireWriteArray();
                if (array[idx][y] > array[idx][y + 1]) {
                    printf("rowCol = %d, i = %d, j = %d Swapping %d & %d\n",
                           idx, x, y, array[idx][y], array[idx][y + 1]);
                    intSwap(&array[idx][y], &array[idx][y + 1]);
                }
                releaseWriteArray();
            }
        }
    } else {
        for(x = 0; x < N - 1; x++) {
            for (y = 0; y < N - x - 1; y++) {

                acquireWriteArray();
                if (array[idx][y] < array[idx][y + 1]) {
                    printf("rowCol = %d, i = %d, j = %d Swapping %d & %d\n",
                           idx, x, y, array[idx][y], array[idx][y + 1]);
                    intSwap(&array[idx][y], &array[idx][y + 1]);
                }
                releaseWriteArray();
            }
        }
    }
    return (void *)NULL;
}

void intSwap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main ()
{

    FILE *input;

    int i = 0, j = 0;

    input = fopen("input.txt" , "r");

    if (input != NULL) {
        for (i = 0; i < N; i++) {

            for (j = 0; j < N; j++) {
                fscanf(input, "%d, ", &array[i][j]);
                printf("%d, ", array[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    } else {
        perror( "There's a problem with the input.txt file, it doesn't seem to be there.");
        exit( EXIT_FAILURE );
    }

    for (i = 0; i < N; i++) {
        pthread_create(&thread[i], NULL, shearSort, (void *)(long)i);
    }

    for (i = 0; i < N; i++) {
        pthread_join(thread[i], NULL);
    }

    for (i = 0; i < N; i++) {
        for (j = 0; j < N; j++) {
            printf("%d, ", array[i][j]);
        }
        printf("\n");
    }
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.