pthread执行陷入无限循环

时间:2019-02-06 19:11:36

标签: c pthreads shared-memory

我正在尝试的是:

  • 创建了四个线程(主要创建了三个线程,线程3创建了线程4)
  • 一个共享内存对象在所有线程之间共享。
  • 另一个共享内存对象在线程2和线程4之间共享。
  • 线程4等待线程2发出信号,直到创建共享内存obj。
  • 所有都是互斥的。

但是我的程序陷入了无限循环。需要解决方案的帮助。

下面是我的源代码:

#include <assert.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>   /* for ftruncate */
#include <sys/mman.h> /* for shm_ and mmap */
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h>    /* For O_* constants */

pthread_t T1, T2, T3, T4;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_one;

int fd;
int *shared_heap;
int *shared_heap2;
int *shared_heap3;
int counter = 0;

//thread one creator func
// *argv is the shared mem obj which is passed while thread is created
void* task1(void *argv) {
    int *var = (int*) argv;
    pthread_mutex_lock(&mutex);
    *var += 1;
     pthread_mutex_unlock(&mutex);
    return NULL;
} 

//thread two creator func
// *argv is the shared mem obj which is passed while thread is created
void* task2(void *argv) {
    int *var = (int*) argv;
    pthread_mutex_lock(&mutex);
    *var += 1;

    pthread_mutex_unlock(&mutex);
    //another mutex to create another shared mem obj
    pthread_mutex_lock(&mutex2);
    shared_heap2 = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,MAP_SHARED, fd, 0);
    assert(shared_heap2);
    counter++;
    //signal 
    if (counter > 0) {
     pthread_cond_signal(&cond_one);
        printf("signal is sent \n");
   }
   pthread_mutex_unlock(&mutex2);

  return NULL;
  }

 //thread four creator func
 //created from thread three
 // *argv is the shared mem obj which is passed while thread is created
 void* task4(void *argv) {
    int *var = (int*) argv;
    pthread_mutex_lock(&mutex);
    *var += 1;
    pthread_mutex_unlock(&mutex);

    pthread_mutex_lock(&mutex2);

    //waiting for signal from thread two
    while (counter > 0) {
    pthread_cond_wait(&cond_one, &mutex2);
    printf("waiting for signal. \n");
 }

    *shared_heap2 = 9;
    pthread_mutex_unlock(&mutex2);


    return NULL;  
}

////thread three creator func
void* task3(void *argv) {
     int *var = (int*) argv;
     pthread_mutex_lock(&mutex);
     *var += 1;
    pthread_mutex_unlock(&mutex);

    //thread four is create from here
     assert(pthread_create(&T4, NULL, &task4, var) == 0);
    assert(pthread_join(T4, NULL) == 0);
     return NULL;
}

int main(void) {

    pthread_cond_init(&cond_one, NULL);
     fd = shm_open("test_shared_var_heap_local", O_CREAT | O_RDWR,S_IRUSR | S_IWUSR);
    assert(fd != -1);
    assert(ftruncate(fd, sizeof(int)) == 0);
    shared_heap = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,MAP_SHARED, fd, 0);

    assert(shared_heap);

    printf("main \n");
    //assert(shared_heap);

    assert(pthread_create(&T1, NULL, &task1, shared_heap) == 0);

    assert(pthread_create(&T2, NULL, &task2, shared_heap) == 0);

    assert(pthread_create(&T3, NULL, &task3, shared_heap) == 0);
    printf("three \n");

    assert(pthread_join(T1, NULL) == 0);
    assert(pthread_join(T3, NULL) == 0);
    assert(pthread_join(T2, NULL) == 0);

     return 0;
}

1 个答案:

答案 0 :(得分:2)

  

但是我的程序陷入了无限循环。

你做

while (counter > 0) {
  pthread_cond_wait(&cond_one, &mutex2);
  printf("waiting for signal. \n");
}

但是 counter task2 中仅设置为1,没有理由暂时退出

无论如何,这不是一个单独的问题,在 mutext2 counter 下的 task2 中将其设置为1并发送信号,所以

  • 第一种可能性 task4 在设置为1之前已经完成,信号无用

  • 其他 task2 运行起来更快,并且在 task4 之前获得 mutex2 ,因此,当 task4 会获取 mutex2 信号已经发送,但是该信号未缓冲,因此 task4

  • 不会接收到该信号

如果您想确保在 task4 完成受 mutex2保护的代码之前执行 task2 中受 mutex2 保护的代码

  • 计数器仍被初始化为0:int counter = 0;
  • mutex2 设为 task4 中的
  • ,只需将 counter 设置为1并删除无用的测试if (counter > 0)即可将信号发送到解锁 mutext2
  • 之前的所有情况 当 mutext2 被获取时,在 task2
  • while (counter > 0) {替换为if (counter == 0) {

附带:

  • 如果 task4 task2 之前获得 mutex2 ,因为 counter 仍为0 task4 等待信号(解锁 mutext2 ), task2 可以获取 mutext2 并发送信号并解锁 mutext2 和完成, task4 接收信号(锁定 mutext2 ),然后解锁 mutext2 并完成
  • 如果 task2 task4 之前获得 mutext2 ,则会将 counter 设置为1并解锁 mutext2 并完成操作, task4 可以获取 mutext2 ,并且不等待信号,因为 counter 为1,因此请解锁 mutext2 完成