【问题标题】:Conditional variable and rwlock deadlock条件变量和rwlock死锁
【发布时间】:2013-11-10 08:38:30
【问题描述】:

我有一个使用条件变量和 rwlock 的简单线程程序。我已经盯着它看了好几个小时,尝试了不同的方法。问题是一个或多个线程在一段时间后在 rwlock 处停止,尽管它没有被锁定以进行写入。也许我错过了一些关于这些锁是如何工作的或它们是如何实现的。

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <unistd.h>

//global variables
pthread_mutex_t mutex;
pthread_cond_t cond;
pthread_rwlock_t rwlock;
int counter;
int listLength = 1;

void* worker(void* arg){
   do {
      usleep(200);
      printf("Before rwlock\n");
      pthread_rwlock_rdlock(&rwlock);
      printf("Before mutex\n");
      pthread_mutex_lock(&mutex);
      printf("Afer mutex\n");
      counter++;
      //signal the main
      if (counter == 5 ||
               (listLength < 5 && counter == listLength)){
          printf("Signal main\n");
          pthread_cond_signal(&cond);
          counter = 0;
      }
      pthread_mutex_unlock(&mutex);
      pthread_rwlock_unlock(&rwlock);
   } while(listLength != 0);

   return NULL;
}


int main(int argc, char* argv[]){
    if (argc != 2){
        perror("Invalid number of args");
        exit(1);
    }
    //get arguments
    int workers = atoi(argv[1]);

    //initialize sync vars
    pthread_rwlockattr_t attr;
    pthread_rwlockattr_setkind_np(&attr,
            PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);
    pthread_rwlock_init(&rwlock, &attr);
    counter = 0;

    //create threads
    pthread_t threadArray[workers];
    int threadOrder[workers];
    for (int i = 0; i < workers; i++){
        threadOrder[i] = i;
        if (pthread_create(&threadArray[i], NULL,
                    worker, &threadOrder[i]) != 0){
            perror("Cannot create thread");
            exit(1);
        }
    }

    while(listLength != 0) {
        //wait for signal and lock the list
        pthread_mutex_lock(&mutex);
        while (pthread_cond_wait(&cond, &mutex) != 0);
        pthread_rwlock_wrlock(&rwlock);
        printf("In write lock\n");

        pthread_mutex_unlock(&mutex);
        pthread_rwlock_unlock(&rwlock);
        printf("release wrlock\n");
    }

    //join the threads
    for (int i = 0; i < workers; i++){
        if (pthread_join(threadArray[i], NULL) !=0){
            perror("Cannot join thread");
           exit(1);
        }
    }

    //release resources
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    pthread_rwlock_destroy(&rwlock);

    return 0;
}

【问题讨论】:

    标签: linux multithreading locking posix


    【解决方案1】:

    看起来这段代码有几个不一致的地方。

    1. 您将mutexrwlock 一起使用,这意味着所有此类线程始终处于锁定状态。如果您删除 rwlock 代码 - 它不会改变行为。

    2. 我看不到pthread_rwlock_init() 调用,假设您在其他地方调用了它。无论如何,请注意你确实调用它,而你不要用同一个rowlock对象调用它两次或更多次。

      同样适用于pthread_rwlockattr_destroy()

    3. 我看不出 pthread_rwlock_rdlock() 在没有写锁的情况下会阻塞的原因。确保你不要这样做。或者你可以对你的mutex进行互锁

    【讨论】:

    • 工作线程在 rwlock 和 mutex 之间有一些额外的工作要做,但我把它拿出来更容易发现问题。如果我取出 rwlock 代码,它不会卡住,但是我需要它来完成额外的工作。 pthread_rwlock_init() 在 main 函数的第一部分。我看不出它不应该工作的任何原因。它只适用于一个工作线程,它会被多个工作线程卡住。
    • 我终于解决了这个问题。死锁是由于在互斥锁被锁定时尝试写锁造成的,因此所有工作线程都会读锁并在互斥锁处等待,而主线程将在写锁处等待。
    猜你喜欢
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多